Issue when rendering a ListViewItem in Xamarin ListView - xaml

Using a ListView in Xamarin, Most of the time, it works well, but for some items, I get a rendering issue, items in the StackLayout are overlapping (stacking on Z axis instead of Y axis!), I am wondering what could cause that:
It seems to happen when cells are recycled to a different height that they initially had.
The xaml is quite simple, a binding for the ListView (grouped) and itemtemplate:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10,5" BackgroundColor="{Binding BackgroundColor}">
<!-- The following IsVisible property is probably what cause
the change of height of cells, and when recycled,
the cells do not resize well -->
<Label Text="{Binding Date}" TextColor="Black" LineBreakMode="NoWrap"
IsVisible="{Binding Date,Converter={StaticResource INNTBC}}" Style="{DynamicResource ListItemTextStyle}" FontSize="12" />
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Participant.FirstName}" TextColor="Black" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="16" />
<Label Text="{Binding Participant.LastName}" TextColor="Black" ineBreakMode="NoWrap" Margin="5,0,0,0" Style="{DynamicResource ListItemTextStyle}" FontSize="16" />
<Label Text="{Binding Participant.BirthDate}" TextColor="Black" LineBreakMode="NoWrap" Margin="5,0,0,0" Style="{DynamicResource ListItemTextStyle}" FontSize="12" />
</StackLayout>
<StackLayout HeightRequest="1" BackgroundColor="LightGray" Margin="20,1,20,1" HorizontalOptions="CenterAndExpand"></StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
Any clue?

The issue comes from CachingStrategy="RecycleElement" applied to the ListView. The height is not well recalculated when recycled.
This is not optimal but at the end I solved it by setting a RowHeight to the ListView.

Related

Keep ListView.Header anchored/sticky/frozen to top when scrolling

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>

Xamarin two labels in each end in one line

I have implemented a listview and in each item I want to have two labels, in each end horizontally. But in reality it just put the two labels next to eachother left aligned.
I read that maybe this is not possible with a stacklayout, as it doesn't take up more space than needed. (Even tried fill and fillandExpand which didn't help.)
Instead I should use a grid. But I have options on my listview, as grouping, refresh, caching, tapped, which I guess I don't have on a grid?
I would like to succeed with a listview if that is possible. Anyone have some insights to this layout issue?
Here is my xaml code:
<?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="MyApp.Page.ItemsTest">
<ListView x:Name="ItemView"
ItemsSource="{Binding ItemGroup}"
CachingStrategy="RecycleElement"
IsGroupingEnabled="true"
HasUnevenRows="True"
ItemTapped="Handle_ItemTapped">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#FFA500" Orientation="Vertical" Padding="10">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Heading}" TextColor="White" FontAttributes="Bold" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="10" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Central part is this:
<StackLayout Orientation="Horizontal" Padding="10" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</StackLayout>
Update:
As requested I have a colored the background of the two labels and the stacklayout. It's the same output if I use HorizontalOptions="End" and HorizontalTextAlignment="End" at the same time or each one alone. Also if I remove the HorizontalOptions="FillAndExpand" on the stacklayout, it's still the exact same graphical output. (The orange color was already present)
Maybe you could use a Grid instead of the StackLayout and place each Label in a different Column:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Grid.Column="1" Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</Grid>
You could also use nested StackLayout
<StackLayout>
<Label />
<Label Text="Gender:" FontAttributes="Bold"/>
<StackLayout Orientation="Horizontal">
<Label HorizontalOptions="Start" Text="First Name: " FontAttributes="Bold"/>
<Entry HorizontalOptions="EndAndExpand" Placeholder="First Name" MaxLength="256" Text="{Binding FirstName}"></Entry>
</StackLayout>
</StackLayout>

Xamarin.Forms can't display image in list

I have a ListView with several items in it. I am running the app as a UWP app on my local machine, but for some reason, displaying an image via a url doesn't work?
The tag I'm using is
<Image Source="https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png" HeightRequest="20" WidthRequest="20" />
I have tried using several different images from different domains as I thought it could be an authorisation issue? But no images that I've tried seem to be working.
As I define the space for the image, there is a gap in the list where it should be.
For reference, here is the whole list code:
<ContentPage Title="Coins">
<ContentPage.Content>
<ListView x:Name="coins" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Spacing="5" Orientation="Horizontal" Padding="10,10,10,10">
<Label Text="{Binding Path=Rank}" FontSize="10" VerticalTextAlignment="Center"/>
<Image Source="https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png" HeightRequest="20" WidthRequest="20" />
<Label Text="{Binding Path=Name}" TextColor="Black" FontSize="19" VerticalTextAlignment="Center"/>
<Label Text="{Binding Path=PercentChange24h, StringFormat='{0}%'}" VerticalTextAlignment="Center" TextColor="{Binding PercentTextColour}"/>
<Label Text="{Binding Path=LivePrice, StringFormat='${0}'}" VerticalTextAlignment="Center" HorizontalTextAlignment="End" HorizontalOptions="EndAndExpand"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
This issue was down to UWP not being able to display images, this works on Android and iOS.

Get SelectedItem from a nested RepeaterView

I am using DottorPagliaccius repeater view thats nested inside another repeaterview. The command RSSFeedSelectedCommand doesnt work unless on top repeater, which in theory makes sense but how can i get it to work?
I have looked into using Converters and bindtoeventcommand but cant see to get them working.
<repeater:RepeaterView x:Name="MainRepeater" SeparatorHeight="25" ItemsSource={Binding Feeds}">
<repeater:RepeaterView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Spacing="10">
<Label Text="{Binding Title}" TextColor="Blue" />
<Label Text="{Binding Description}" TextColor="Red" FontSize="12" />
<repeater:RepeaterView x:Name="MainRepeater2" EmptyText="No elements" ShowSeparator="true" SeparatorHeight="2" SeparatorColor="Silver" ItemsSource="{Binding Items}" SelectedItemCommand="{Binding RSSFeedSelectedCommand}">
<repeater`enter code here`:RepeaterView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding Image.Url}"></Image>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}" TextColor="Black" />
<Label Text="{Binding Description}" TextColor="Black" FontSize="12" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</repeater:RepeaterView.ItemTemplate>
</repeater:RepeaterView>
</StackLayout>
</ViewCell>
</DataTemplate>
</repeater:RepeaterView.ItemTemplate>
</repeater:RepeaterView>
The Repeater was trying to find the command in Feeds however exists in the ViewModel.
<repeater:RepeaterView x:Name="MainRepeater2" EmptyText="No elements" ShowSeparator="true" SeparatorHeight="2" SeparatorColor="Silver" ItemsSource="{Binding Items}" SelectedItemCommand="{Binding Source={x:Reference RSSPage}, Path=BindingContext.RSSFeedSelectedCommand}">
and you have to name the page:
<ContentPage x:Name="PageName" />
If my assumption is correct, your class structure should be something like,
ViewModel
|__List of Feeds
|__List of Items
|__RSSFeedSelectedCommand
So, DataContext of your inner repeater control (MainRepeater2) will be Feed. So, try with DataContext of outer repeater control. Like,
<repeater:RepeaterView x:Name="MainRepeater2" ItemsSource="{Binding Items}"
SelectedItemCommand="{Binding DataContext.RSSFeedSelectedCommand,
ElementName=MainRepeater}"/>
For Xamarin:
<repeater:RepeaterView x:Name="MainRepeater2" ItemsSource="{Binding Items}"
SelectedItemCommand="{Binding DataContext.RSSFeedSelectedCommand,
Source={x:Reference MainRepeater}}"/>

Xamarin.Forms Vertical StackLayout in ListView displays only one (first) Child

<ListView
ItemsSource="{Binding Messages}"
Grid.ColumnSpan="2"
HeightRequest="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label
Text="{Binding When}"
XAlign="Center"/>
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Message}"
XAlign="Start"/>
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am rendering a custom ListView in Xamarin.Forms application. The StackLayout which contains two Labels (to which "Message" and "Sender" has been bound), currently displays only one child. With the code above, it displays only "Message". If I change code to be
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
<Label
Text="{Binding Message}"
XAlign="Start"/>
</StackLayout>
it displays only sender. In short it is displaying only first child. What have I done wrong here ?
Issue was similar to what #Grisha had pointed out. RowHeight was proving to be lesser, and the second StackLayout was getting clipped.
The solution was to set HasUnevenRows property of the ListView to be TRUE. Thus, RowHeight was calculated automatically.