I want to have some space around the Image cell items of a ListView:
<StackLayout>
<ListView ItemsSource="{Binding Items}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
but there's no Margin property available for the ImageCell?
EDIT
I did what cvanbeek suggested before posting the question:
<DataTemplate>
<StackLayout Padding="5">
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</StackLayout>
</DataTemplate>
but I got this exception:
Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
in the OnCreate method in MainActivity.cs
DataTemplate definition
Only View can be put inside DataTemplate, however StackLayout is Layout.
Use a ViewCell instead , it is more flexible and controllable.
<ListView >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20" Orientation="Horizontal" >
<Label Margin="20" Text="123"/>
<Image Source="Assets/StoreLogo.png"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Related
How do I conditionally render a particular text in Xamarin Forms 5?
For example, I get some data from my API backend for a vendor and there may be an address in the database for this vendor or not.
If I do have vendor's address, I'd like to display it and if I don't have an address, I'd like to display something like "n/a".
Is there a way to handle this in the XAML page or do I have to handle it in code behind?
UPDATE:
Here's what the XAML page for the phone numbers ListView looks like:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers, TargetNullValue='n/a'}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
You can use xaml binding with TargetNullValue
<Label Text="{Binding Location, TargetNullValue='n/a'}"/>
If you don't have an address your API or your code should set Location to null in order for TargetNullValue to work.
Update (reply to this comment).
Use TargetNullValue in the bindings inside ItemTemplate (applies to each single element) and not on itemsource binding:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay, TargetNullValue='n/a'}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
My ListView is bound to MyTexts list. Nevertheless i need to bind TextCell's Text to property that is not comming from Texts (StandAloneProperty). How can i do that?
<ListView
SelectedItem="{Binding SelectedText, Mode=TwoWay}"
ItemsSource="{Binding MyTexts}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding StandAloneProperty, StringFormat='Value: {0}'}"
TextColor="{Binding Color}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Set your binding Source to the current page, and access to StandAloneProperty, from BindingContext which is your ViewModel.
<ContentPage x:Name="pageRef"
...
<ListView
SelectedItem="{Binding SelectedText, Mode=TwoWay}"
ItemsSource="{Binding MyTexts}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding Source={x:Reference pageRef} Path=BindingContext.StandAloneProperty, StringFormat='Value: {0}'}"
TextColor="{Binding Color}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
How to keep the built-in Header of a ListView frozen to the top when scrolling vertically down through the ListView items?
Before flagging as duplicate: I tried to apply answers in Keep ListView.HeaderTemplate visible/static/sticky in UWP for Xamarin.Forms targeting Android without success.
Short code sample:
<ListView ItemsSource="{Binding MyList}"
HasUnevenRows="True"
SeparatorVisibility="Default"
CachingStrategy="RecycleElement">
<ListView.Header>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is an alternative approach to this if the list isn't long
<StackLayout>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
<StackLayout BindableLayout.ItemsSource="{Binding MyList}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}"/>
<!-- boxview as separator -->
<BoxView HeightRequest="1" Color="Aqua" HorizontalOptions="FillAndExpand"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
In my XAML File after changing some code inside it and then debug on my phone, the changes I made do not reflect on my phone. It keep showing my old code.
Old code :
<ListView
ItemsSource="{Binding Allgroups}"
RowHeight="75"
IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding NameNative}"></Label>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding TitleWithItemCount}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
</ListView>
new code :
<Label Text="HELOO WORLD "></Label>
I Noticed every time i run the code , it keep showing the list.I have to click the save button then the list disappear and hello world appear .
I reset VS settings and relaunched it .
worked for me
<CollectionView ItemsSource="{Binding Categoriesxx}" IsGrouped="True">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="1" VerticalItemSpacing="5" HorizontalItemSpacing="5"></GridItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout >
<Label Text="{Binding NameNative}"></Label>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<StackLayout BackgroundColor="AliceBlue">
<Label Text="{Binding Name}" FontSize="Title"></Label>
<Button Image="{Binding StateIcon}"
BackgroundColor="Transparent"
BorderColor="Transparent"
BorderWidth="0"
Command="{Binding BindingContext.ExpandCommand ,Source={x:Reference ServiceListPage}}"/>
</StackLayout>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</CollectionView>
Using this code
x:Class="Fit_Plans.TimelinePage"
Title="Timeline"
BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }
<ContentPage.Content>
<ListView
ItemsSource="{ Binding TimelineList }"
SeparatorVisibility="None"
BackgroundColor="{ DynamicResource BasePageColor }"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<StackLayout>
<Grid x:Name="GridTasks">
<local:TimelineItemTemplate
Padding="{ DynamicResource MainWrapperPadding }"/>
</Grid>
</StackLayout>
<artina:Button
Clicked="OnNextButtonTapped"
Style="{DynamicResource PrimaryActionButtonStyle}"
Text="Order"
VerticalOptions="EndAndExpand"
WidthRequest="{ artina:OnOrientationDouble
LandscapeTablet=600 }"
HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Fill,
PortraitTablet=Fill,
LandscapeTablet=Center }"/>
<StackLayout>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
Result :
But if I want to display the order Button only 1 time at the end of the list view , how to achieve that?
I have tried this with no success :
<ContentPage.Content>
<ListView
ItemsSource="{ Binding TimelineList }"
SeparatorVisibility="None"
BackgroundColor="{ DynamicResource BasePageColor }"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<StackLayout>
<Grid x:Name="GridTasks">
<local:TimelineItemTemplate
Padding="{ DynamicResource MainWrapperPadding }"/>
</Grid>
</StackLayout>
<StackLayout>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
<artina:Button
Clicked="OnNextButtonTapped"
Style="{DynamicResource PrimaryActionButtonStyle}"
Text="Order"
VerticalOptions="EndAndExpand"
WidthRequest="{ artina:OnOrientationDouble
LandscapeTablet=600 }"
HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Fill,
PortraitTablet=Fill,
LandscapeTablet=Center }"/>
It displayed the button at the end but with an empty list
ListView provides HeaderTemplate and FooterTemplate. You should put your button inside FooterTemplate as follows:
<ListView ItemsSource="{ Binding TimelineList }" SeparatorVisibility="None" BackgroundColor="{ DynamicResource BasePageColor }" HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
.................
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<ContentView>
//Put your button here
</ContentView>
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
As of previous answer you can put in in footer or if you'd want to keep he button inside the cell template then wrap the button in with a IsVisible = your custom converter, that would check if (myIndex == totalListCount) then the button would be displayed for the last item in list only.