Please I need help.
I have my Xamarin Form app that works very well with DataBinding to its View Model named OrderDetailViewModel.
But today I have to add another DataBinding field in line 10 Binding OrderStatusMessage that is bind to its Xaml.cs file (code behind) but out of curiosity this field doesn't work I mean it is not changing the Label Text dynamically after binding the label text to a property located in its xaml.cs file (code behind file).
In line 4 you can find the data binding to MVVM file called OrderDetailViewModel which works well.
But the issue is in line 10 Binding OrderStatusMessage which is a DataBinding to its own xaml.cs file doesn't change the Label text to new message.
I tested the same code Binding OrderStatusMessage outside of the CollectionView.ItemTemplate tag and it's working properly, so only when I put inside CollectionView.ItemTemplate tag that's is not pulling the updated text.
In the below code there's only one property that is bind to its xaml.cs file (code behind) which is in line 10 {Binding OrderStatusMessage} that doesn't get the updated text, the rest are bind to the MVVM which works well.
PS : I would like to add Multiple Binding to this below code in line 4 :
filename : OrderDetailViewPage.xaml
<CollectionView.ItemTemplate >
<DataTemplate >
<StackLayout
xct:TouchEffect.LongPressCommand="{Binding LongPressCommand, Source={RelativeSource AncestorType={x:Type local:OrderDetailViewModel}}}"
xct:TouchEffect.LongPressCommandParameter="{Binding .}"
xct:TouchEffect.PressedScale="1.2"
xct:TouchEffect.NativeAnimation="True">
<StackLayout>
<Label Text="{Binding OrderStatusMessage}" HorizontalOptions="CenterAndExpand" FontFamily="fasolid" FontSize="18" FontAttributes="Bold" TextColor="Black"/>
</StackLayout>
<Label Text="{Binding Id}"
FontSize="Medium"/>
<Label Text="Order number" HorizontalOptions="CenterAndExpand"/>
<Label Text="{Binding OrderId}"
TextColor="Purple" FontAttributes="Bold"
FontSize="Large" HorizontalOptions="CenterAndExpand"/>
<Label Text="{Binding OrderDetail}"
TextColor="Purple"
FontSize="Small" />
<Label Text="{Binding OrderDate}"
TextColor="Purple"
FontSize="Small" />
<Label Text="{Binding IsOrderComplete}"
TextColor="Purple"
FontSize="Small" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
Have you tried bind your Label inside CollectionView.ItemTemplate using Path property?
Like this : <Label Text = "{Binding Path=OrderStatusMessage, Source = {x:Reference pageName}}"/>
Related
I want to use just 1 list view for my ContentPage. The problem is that I need to bind two different types of data from an object list.
I tried to set the bind from code but is working for just 1 list elements
The first ItemSource is the one that is binding the elements.
The second one contains different data but I want to use the same XAML code to display it.
In the xaml part, lets say I can/want reuse: {Binding sRFC} and {Binding sNombre}
PickLista.ItemsSource = lst; // Bound list correctly - this is in code
PickLista.ItemsSource = ls; // List 2 with other object elements - this is in code
<ListView x:Name="myLista" HasUnevenRows="true" Margin="5" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="5" HeightRequest="40" >
<Label Text="{Binding iId}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start" TextColor="Black" FontSize="15"/>
<Label Text="{Binding sRFC}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start" TextColor="Black" FontSize="15"/>
<Label Text="{Binding sNombre}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start" TextColor="Black" FontSize="15"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I want to be able to display both object elements in the same list view, or if i can use another listview in the same position over the other (via XAML).
If those properties are named the same in both classes and satisfy everything required for binding it will work. So either you have different name or properties in some class are not public or don't have getters...
I have a listview. This list view has 5 rows with two buttons namely A & B. When I tap on button A on a row, I want to change the image on A as well as B on the same row and vice-versa. I am able to individually tap and change the image on the same button but don't know how to change the image on the other button. Here is my listview:
<ListView x:Name="GroupedView" SeparatorColor="Transparent" GroupDisplayBinding="{Binding Title}" IsGroupingEnabled="true" HasUnevenRows="true" >
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="5" BackgroundColor="#E2F5F9">
<Label Text="{Binding Title}" TextColor="{StaticResource NavyBlue}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="2" Padding="5">
<StackLayout VerticalOptions="FillAndExpand">
<Label Text="{Binding QuestionName}" />
</StackLayout>
<StackLayout IsVisible="{Binding ShowYesNo}" Spacing="15" Orientation="Horizontal" HorizontalOptions="End">
<Button ClassId="Yes" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding YesChoiceImg}" />
<Button ClassId="No" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding NoChoiceImg}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am then using the sender to identify the class ID and change the image of the button.
Should I be using a command? Should I be doing something else? Please help. Thanks
If you want to use the CommandParameter you should be using a Command. At the moment you're mixing 2 different ways to handle the click.
One thing to note though is that if you use a command you usually want to bind it to a Command that is defined on your ViewModel but since inside the DataTemplate your BindingContext is the ListView item instead of the ViewModel so you have to reference around that. Something like this should work:
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="2" Padding="5">
<StackLayout VerticalOptions="FillAndExpand">
<Label Text="{Binding QuestionName}" />
</StackLayout>
<StackLayout IsVisible="{Binding ShowYesNo}" Spacing="15" Orientation="Horizontal" HorizontalOptions="End">
<Button ClassId="Yes" Command="{Binding Path=BindingContext.ButtonCommand, Source={x:Reference MyQuestionPage}}" CommandParameter="{Binding .} Image="{Binding YesChoiceImg}" />
<Button ClassId="No" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding NoChoiceImg}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
Note here that you have to give your ContentPage an x:Name (so you can reference it and call the BindingContext on it). And the "{Binding .}" binds to the current list item. So no need to search for it on id you can just plug it into the command directly!
I've been working on a UWP app for quite some time. We recently decided to transition over to Xamarin so that we can easily support Android alongside UWP. I've had no issues setting up a PCL to use for our code base. Now I'm running into some nightmares when trying to rewrite our UI for Xamarin.Forms. I'm trying to accomplish something relatively simple and I must be doing something hilariously wrong, but, I cannot figure out what.
I want to display a listView. Here's the XAML:
<ContentPage.Content>
<StackLayout>
<Label Text="This is the bill page."
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<ListView x:Name="lvBills"
ItemsSource="{Binding Bills}"
SelectedItem="{Binding SelectedBill}">
<ListView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Amount}"
TextColor="White"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"/>
<Label Text="{Binding DueDate}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
TextColor="White"/>
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
When I run it, the listView populates with each item in my observable collection. However, no text is actually displayed..even if I remove the bindings and use some placeholder text. Additionally, if I click on any item in the listView, this exception crashes the program.
System.InvalidCastException: Unable to cast object of type
'Xamarin.Forms.StackLayout' to type 'Xamarin.Forms.Cell'.
at Xamarin.Forms.Internals.TemplatedItemsList`2.ActivateContent(Int32 index,
Object item)
at Xamarin.Forms.Internals.TemplatedItemsList`2.CreateContent(Int32 index, O
Object item, Boolean insert)
at Xamarin.Forms.Internals.TemplatedItemsList`2.GetOrCreateContent(Int32
index, Object item)
at Xamarin.Forms.Internals.TemplatedItemsList`2.get_Item(Int32 index)
at Xamarin.Forms.L
I can't figure out any search that yields any meaningful results. I've tried some other things: Adding a binding for ItemSelected in the xaml. I've tried to wire up delegates in the xaml.cs But I cannot make any progress. So, what am I doing wrong?
You need a ViewCell inside a DataTemplate:
<ContentPage.Content>
<StackLayout>
<Label Text="This is the bill page."
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<ListView x:Name="lvBills"
ItemsSource="{Binding Bills}"
SelectedItem="{Binding SelectedBill}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell> <!-- <----- Add this -->
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Amount}"
TextColor="White"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"/>
<Label Text="{Binding DueDate}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
TextColor="White"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
I have 2 labels that need to use different fonts to make single label this
"My Company (c)" (copywrite symbol). "My Company " will be a Large font and the '(c)' a small font. I can't get them to appear as 1 single label. There seems to be spacing issues. I have tried the following.
<StackLayout Grid.Row="1" Orientation="Horizontal">
<Label
x:Name="lbCo"
Text="My Company"
Style="{DynamicResource LargeLabel}"/>
<Label
x:Name="lbcopywrite"
Text="©"
Margin="0,-7,0,0"
Style="{DynamicResource SmallLabel}"/>
</StackLayout>
But it appears like "My Company (spaces) (c)"
Any ideas how can make it look like "My Company(c)", always on the same line and together?
There is another way, but you can't assign a Style directly to the text, but you can choose numerous font options. You can still set a Style to the main label though.
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Company" FontAttributes="Bold"/>
<Span Text=" ©" FontSize="Micro" />
</FormattedString>
</Label.FormattedText>
</Label>
If you want binding, you need to create a Converter, that returns a FormattedString, and assign to FormattedText. You could create a Converter with Parameters if you want to reuse it, with different styles.
<Label FormattedText="{Binding Text, Converter={StaticResource FormattedStringConverter}}" />
You can specify the Spacing property on the StackLayout:
<StackLayout Grid.Row="1" Orientation="Horizontal" Spacing="0">
<Label x:Name="lbCo"
Text="My Company"
Style="{DynamicResource LargeLabel}"/>
<Label x:Name="lbcopywrite"
Text="©"
Margin="0,-7,0,0"
Style="{DynamicResource SmallLabel}"/>
</StackLayout>
By default, the value is 6.
You should use the VerticalTextAlignment property and set it to center. You should also set the label margin to 0 for both.
<StackLayout Grid.Row="1" Orientation="Horizontal">
<Label
x:Name="lbCo"
Text="My Company"
VerticalTextAlignment="Center"
Style="{DynamicResource LargeLabel}"/>
<Label
x:Name="lbcopywrite"
Text="©"
VerticalTextAlignment="Center"
Style="{DynamicResource SmallLabel}"/>
</StackLayout>
I use the below code to bind data to a label for changing a slider value and it works fine.
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" >
<Label Text="{Binding Source={x:Reference slider1}, Path=Value, StringFormat='Value is {0:F2}'}"
Opacity="{Binding Source={x:Reference slider1}, Path=Value}"
x:Name="label1"/>
<Slider x:Name="slider1"></Slider>
</StackLayout>
In xaml.cs page, I have initiated the slider value to 0.5
public MainPage()
{
InitializeComponent();
slider1.Value=0.5;
}
But, when I want to Binding data using BindingContext, it does not show the output correctly.
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" >
<Label BindingContext="x:Reference slider1"
Text="{Binding Value, StringFormat='Value is {0:F2}'}"
Opacity="{Binding Value}"
x:Name="label1"/>
<Slider x:Name="slider1"></Slider>
</StackLayout>
What is the problem with my second xaml?
I think, you have missed the {}. Try
<Label BindingContext="{x:Reference slider1}"
instead of
<Label BindingContext="x:Reference slider1"
If you use BindingContext then the object should implement INotifyPropertyChanged.
Slider doesn't implement this interface. Generally, you should assign BindableProperty to BindingContext.
https://developer.xamarin.com/guides/xamarin-forms/xaml/bindable-properties/