Add elements to Zxing barcode Xaml content page, Xamarin.forms - xamarin

I am using Zxing.Net.Mobile.Forms to display a barcode. I'm not sure how to add other elements along with the barcode on one page. I've tried adding it in both c# and xaml but my additional elements do not show. I want to add a label after the barcode and a picture above the barcode.
Barcode.xaml.cs
public partial class BarCode : ContentPage
{
ZXingBarcodeImageView barcode;
public BarCode()
{
InitializeComponent();
barcode = new ZXingBarcodeImageView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
};
barcode.BarcodeFormat = ZXing.BarcodeFormat.CODE_128;
barcode.BarcodeOptions.Width = 300;
barcode.BarcodeOptions.Height = 150;
barcode.BarcodeOptions.Margin = 10;
barcode.BarcodeValue = Helpers.Settings.CardNumber;
Content = barcode;
}
}
Barcode.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LoyaltyWorx.BarCode"
BackgroundImage="NewBg.jpg">
<ContentPage.Content>
<StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

You are assigning Content with barcode. Hence, anything in the XAML will be overwritten.
You could do this instead. Add the ZXingBarcodeImageView to your XAML like:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
x:Class="LoyaltyWorx.BarCode"
BackgroundImage="NewBg.jpg">
<ContentPage.Content>
<StackLayout>
<zxing:ZXingBarcodeImageView x:Name="Barcode"
BarcodeFormat="CODE_128"
HorizontalOptions="Fill" VerticalOptions="Fill"
WidthRequest="300" HeightRequest="150" Margin="10" />
<!-- add other stuff here -->
</StackLayout>
</ContentPage.Content>
</ContentPage>
Then you can remove your code in the constructor so it looks something like:
public partial class BarCode : ContentPage
{
public BarCode()
{
InitializeComponent();
Barcode.BarcodeValue = Helpers.Settings.CardNumber;
}
}
Bonus: If you are using the MVVM pattern, you could also bind BarcodeValue to a ViewModel and eliminate all the code behind by adding BarcodeValue="{Binding CardNumber}" to the ZXingBarcodeImageView in the XAML and somewhere setting the Binding Context.

Here is what you want:Showing barcode, an image on the center of it (overlapping), and a label after the barcode
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
x:Class="LoyaltyWorx.BarCode">
<ContentPage.Content>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image Source="{Binding BarcodeImage}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"/>
<Image Source="{Binding OtherImage}"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 100, 100"/>
</AbsoluteLayout>
<Label Text="MyLabel"/>
</ContentPage.Content>
</ContentPage>

Related

Xamarin Forms TemplateBinding

I understand XAML doesn't really have a facility to extend (inherit) one page from another, but I have seen others use ControlTemplates to achieve this effect.
I am having trouble getting a Binding to work in this scenario. In my example, I have a base ContentPage extended by MainPage. Also, I am using FreshMVVM, so that is why the view model is minimal as FreshMVVM handles all the plumbing of property change notifications.
When the app runs, the label should get the value "Xamarin Forms Header" initialized in the MainPageModel.
I have the fully runnable source on github here, but here's the code. Can someone see what the issue is?
MainPage.xaml
<local:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage">
<StackLayout>
</StackLayout>
</local:PageBase>
MainPageModel.xaml
public class MainPageModel : FreshBasePageModel
{
public MainPageModel()
{
LabelText = "Xamarin Forms Header";
}
public string LabelText { get; set; }
}
PageBase.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleApp.PageBase">
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding LabelText}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
</ContentPage>
you could try to change like this:
MainPage.xaml :
<?xml version="1.0" encoding="utf-8" ?>
<local:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage"
LabelText ="{Binding LabelText} "
>
<StackLayout>
</StackLayout>
</local:PageBase>
PageBase.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleApp.PageBase">
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{TemplateBinding LabelText}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
</ContentPage>
in your PageBase.xaml.cs:
public partial class PageBase : ContentPage
{
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create("LabelText", typeof(string), typeof(PageBase), "Control Template Demo App");
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
}
public PageBase ()
{
InitializeComponent ();
}
}
you could refer to TemplateBinding
TemplateBinding doesn't bind to the View Model so whole code is fundamentally wrong, please read about the topic https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-templates/template-binding
Also of note, this would likely work if you used Binding instead of TemplateBinding, but I don't think it makes sense to do that as said something is fundamentally wrong.

How to bind a nested Layout with external ContentView in Xamarin.Forms?

I have a Page with a StackLayout using BindableLayout.ItemsSource, inside each item I have a ListView, for each item in this nested ListView I need to do a Binding to a property on the Page's ViewModel. I'm trying to use the Source+Path approach but the app crashes as soon as I open the page that contains this structure.
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="BindableLayoutReferenceBug.ListViewPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BindableLayoutReferenceBug">
<StackLayout BindableLayout.ItemsSource="{Binding Items}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<local:MessageListViewTemplate />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage>
MessageListViewTemplate.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="BindableLayoutReferenceBug.MessageListViewTemplate"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="listView">
<ListView ItemsSource="{Binding Options}">
<ListView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" />
<Button
BackgroundColor="Blue"
Command="{Binding Source={x:Reference Name=listView}, Path=Parent.BindingContext.ShowMessageCommand}"
CommandParameter="{Binding .}"
Text="Show Message" />
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentView>
The exception shows that there is a problem finding the reference to the x:Name I used: Can not find the object referenced by listView
This only happens when I have a nested structure as I mentioned (StackLayout with BindableLayout > ListView). I'm not sure if this is not a supported scenario or if it is a bug.
I tried using different Paths for the binding, but since this is a problem parsing the XAML not finding the x:Name referenced, I don't think it even starts evaluating my Path.
Am I doing something wrong or is this a bug in Xamarin.Forms?
Xamarin.Forms version used: 3.6.0.293080
Repro sample: https://github.com/akamud/BindableLayoutReferenceBug
Maybe, x:Name wasn't recognized at runtime even though you have set it to your content view in XAML. You could raise an issue on GitHub.
Here I tried this binding using code behind and it works fine. You could use it as an alternative:
public MessageListViewTemplate()
{
InitializeComponent();
listView.ItemTemplate = new DataTemplate(() =>
{
ViewCell viewCell = new ViewCell();
Label label = new Label();
label.SetBinding(Label.TextProperty, new Binding("."));
Button button = new Button() { Text = "Show Message", BackgroundColor = Color.Blue };
button.SetBinding(Button.CommandProperty, new Binding("Parent.BindingContext.ShowMessageCommand", source: ContentView));
button.SetBinding(Button.CommandParameterProperty, new Binding("."));
viewCell.View = new StackLayout
{
Children =
{
label,
button
}
};
return viewCell;
});
}
XAML:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BindableLayoutReferenceBug.MessageListViewTemplate"
x:Name="ContentView">
<StackLayout>
<ListView ItemsSource="{Binding Options}" x:Name="listView" HasUnevenRows="True">
</ListView>
</StackLayout>
</ContentView>
Here, I defined the parent content view as ContentView and named ListView listView.
Please notice that the list view's data template should be a view cell. So I used a view cell to wrap the content here.
It was a bug after all, it is now fixed and the above should work: https://github.com/xamarin/Xamarin.Forms/issues/6192

Custom TitleView shows small white border on either side

In the screenshot below, my app is showing a title bar with a small white border on the left and right sides. How can I get rid of this border when setting a custom TitleView? In the case below, the red box should stretch from edge to edge of the screen, but you can see the small white border on either side.
Here I set up the NavigationPage.
public partial class App : Application
{
public App()
{
InitializeComponent();
ContainerRegistration.Register();
var authPage = FreshPageModelResolver.ResolvePageModel<LoginPageModel>();
var authPageNavigation = new FreshNavigationContainer(authPage, NavigationContainerNames.AuthenticationContainer);
MainPage = authPageNavigation;
}
}
Here is the XAML that references the navigation page to set the TitleView contents to a BoxView.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:WP.MobileMidstream.Device.Pages"
x:Class="WP.MobileMidstream.Device.Pages.LoginPage"
Visual="Material">
<NavigationPage.TitleView>
<BoxView BackgroundColor="Red" />
</NavigationPage.TitleView>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Entry Placeholder="Username" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
It seems that the Navigation bar has a default Padding set (although i could not find that documented anywhere), and i could not find a way to change that (without using custom renderers).
Nevertheless, if what you are looking for is simply get the whole bar of a desired color, you could set the BarBackgroundColor property of your page as follows:
protected override void OnAppearing()
{
base.OnAppearing();
((NavigationPage)App.Current.MainPage).BarBackgroundColor = Color.Red;
}
I suggest you don't add BoxView in NavigationPage.TitleView, just set BarBackgroundColor in App.xaml.cs, like this:
<?xml version="1.0" encoding="utf-8" ?>
<!--<NavigationPage.TitleView>
<BoxView BackgroundColor="Red" VerticalOptions="CenterAndExpand" />
</NavigationPage.TitleView>-->
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Entry Placeholder="Username" />
</StackLayout>
</ContentPage.Content>
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage()) { BarBackgroundColor=Color.Red};
}
It really depends on solution which you use for your toolbar.
Mostly updating toolbar in your android solution would be enough.
If it wont work it could be in your toolbar renderer (if you use) or in styles.xml
Check out for more solutions
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
Full Toolbar.xml
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_my_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
This saved me! Add it in App.xaml
under ResourceDictionary
<ResourceDictionary>
<!--Global Styles-->
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="Red"/>
<Setter Property="BarTextColor" Value="White"/>
</Style>
</ResourceDictionary>

Can I redefine a ContentPage to add some elements to it?

My application uses many ContentPages like this:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
xmlns:template="clr-namespace:Japanese.Templates"
x:Class="Japanese.Views.HelpTab.SettingsPage"
Title="Settings Screen Help"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<ScrollView>
<StackLayout Spacing="0">
<Content goes here/>
</StackLayout>
</ScrollView>
</ContentPage.Content>
Is there a way that I could create a new type of page called ScrollableContentPage that already has the <ScrollView> and <StackLayout Spacing="0"> elements?
Something like this:
<ScrollableContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
xmlns:template="clr-namespace:Japanese.Templates"
x:Class="Japanese.Views.HelpTab.SettingsPage"
Title="Settings Screen Help"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<Content goes here/>
</ContentPage.Content>
I believe that there are several possibilities. We are using a nested ContentView that is bound to the inner content. Just add the ContentView the XAML of the page you'd like to reuse
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
xmlns:template="clr-namespace:Japanese.Templates"
x:Class="Japanese.Templates.ScrollableContentPage"
BackgroundColor="{DynamicResource PageBackgroundColor}"
x:Name="ContentPage">
<ContentPage.Content>
<ScrollView>
<ContentView Content="{Binding Source={x:Reference ContentPage}, Path=InnerContent}" />
</ScrollView>
</ContentPage.Content>
</ContentPage>
And in the code behind you'll have to define a bindable property (actually I don't know if it has to be a bindable property, but you'll need the change notification anyway, hence a BindableProperty should be fine)
public static readonly BindableProperty InnerContentProperty = BindableProperty.Create(nameof(InnerContent), typeof(View), typeof(ScrollableContentPage));
public View InnerContent
{
get => (View)this.GetValue(InnerContentProperty);
set => this.SetValue(InnerContentProperty, value);
}
Now you can use the ScrollableContentPage as you would use any other page (well, you need the namespace imports, but ...)
<template:ScrollableContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
xmlns:template="clr-namespace:Japanese.Templates"
x:Class="Japanese.Views.HelpTab.SettingsPage"
Title="Settings Screen Help">
<template:ScrollableContentPage.InnerContent>
<!-- You content goes here -->
</template:ScrollableContentPage.InnerContent>
</template:ScrollableContentPage>
You can even simplify this, by adding the attribute to ScrollableContentPage.
[ContentProperty(nameof(InnerContent))]
public class ScrollableContentPage : ContentPage
{
// ...
}
This way you can omit specifiing InnerContent explicitly and use your ScrollableContentPage like this:
<template:ScrollableContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
xmlns:template="clr-namespace:Japanese.Templates"
x:Class="Japanese.Views.HelpTab.SettingsPage"
Title="Settings Screen Help">
<!-- You content goes here -->
</template:ScrollableContentPage>

Carousel view does not return anything

I'm implementing a carrousel in my project, but the way I'm implementing it is not returning me anything, to some error in my code? Am I forgetting any options? Reference Xamarin.Forms.CarouselView is already attached
OBS: I am developing crossplataform
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Hanselman.Portable.Views.PodcastPage" Title="{Binding Title}"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
Icon="{Binding Icon}" IsBusy="{Binding IsBusy}"
xmlns:cv="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView">
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout BackgroundColor="White" VerticalOptions="FillAndExpand">
<cv:CarouselView x:Name="car" HeightRequest="200">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical">
<Image Aspect="AspectFit" Source="{Binding imgs}"/>
</StackLayout>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
</AbsoluteLayout>
</ContentPage>
public class Dados
{
public string imgs { get; set; }
}
public PodcastPage()
{
InitializeComponent();
List<Dados> lista = new List<Dados>();
lista.Add(new Dados
{
imgs = "car1.png",
});
lista.Add(new Dados
{
imgs = "car2.png",
});
lista.Add(new Dados
{
imgs = "car3.png",
});
car.ItemsSource = lista;
}
<cv:CarouselView x:Name="MainCarouselView" HeightRequest="100">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="jose" FontSize="50" TextColor="Black"/>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
I tried without image only with the label inside and showing me my name, even so it does not return anything to me, but when I remove the carousel it works, seeing that I verified that my error is in my carousel, it is not an image question

Resources