Xamarin Faster then listview - c#

Im buildining a novel-manga app.
When i came to novels there was about 2000 chapthers and i need to render them all at once.
Im using a listview to render them but its to damnt slow.
I was wondering if there is a faster solution like a renderer or somthing i could build that will work faster.
Here is my current XAML
<ListView ItemsSource="{Binding Chapters}"
x:Name="grdChapters"
ItemSelected="GrdChapters_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="5" HeightRequest="30">
<StackLayout Orientation="Horizontal">
<Label TextColor="Black" Text="{Binding Name}" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Style="{StaticResource header}" FontAttributes="None" />
<Image Source="right.png" HorizontalOptions="End" IsVisible="{Binding Completed}" WidthRequest="16" HeightRequest="16" Aspect="AspectFit" />
</StackLayout>
<BoxView Style="{StaticResource lightLine}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

The RecycleElementAndDataTemplate should improve your performance, because even though you're not using any dynamic images, the datatamplate is the same for all of the items in the list and it'll get optimized.
If that doesn't help, I'd recommend using the glidex library for Xamarin.Android, it makes scrolling a lot smoother.

Related

Change CollectionView EmptyView Text Color

I'm trying to change a CollectionView's EmptyView Text's font color. It seems to automatically change from black to white when switching between the native device's Light theme and Dark theme. TextColor is not an attribute, unfortunately.
I'm new to Xamarin.Forms, I'd like to apologize, first, if I haven't displayed enough code, please let me know if there's anything else you need.
My code is located in the AppShell.xaml
<Shell.FlyoutHeaderTemplate>
<DataTemplate>
<Grid HeightRequest="{Binding ShellHeight}"
ColumnSpacing="0"
RowSpacing="0"
RowDefinitions="Auto, Auto"
ColumnDefinitions="45, Auto">
<CollectionView
Margin="15,0,0,0" Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="2" Grid.RowSpan="2"
ItemsSource="{Binding ShellModelList}"
SelectionMode="Single"
EmptyView="No items to display" //<-- trying to change this text's color
SelectionChanged="OnCollectionViewSelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="1"
RowSpacing="10"
ColumnDefinitions="25, Auto"
RowDefinitions="35">
<Image Grid.Column="0">
<Image.Source>
<FontImageSource
x:Name="imgMenuItem"
FontFamily="{StaticResource NextupFont}"
Glyph="{Binding IconName}"
Color="{StaticResource NuCyanBlue}"
Size="8" />
</Image.Source>
</Image>
<Label x:Name="lblMenuItem"
Grid.Column="1"
Margin="10,0,0,0"
Text="{Binding Text}"
TextColor="{AppThemeBinding Light={DynamicResource NuCyanBlue}, Dark={DynamicResource NuBlack}}"
FontSize="12"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</DataTemplate>
</Shell.FlyoutHeaderTemplate>
Well, I think what you should be doing is creating your custom EmptyView.
<CollectionView.EmptyView>
<StackLayout
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
<Label
FontAttributes="Bold"
FontSize="18"
TextColor="Black"
HorizontalTextAlignment="Center"
Text="No items to display" />
</StackLayout>
</CollectionView.EmptyView>
Good luck! feel free to get back if you have any queries.

How to set the width of the fixed columns in xamarin

I have a ListView that shows chemical residues, the problem is that when I add a particular residue ("BORRAS") my column configuration goes to shit as shown in the following figure
I think there is a nomenclature to set the width of the columns, how can I solve this? How can I make my ListView look homogenous?
I attach my ListView.XAML:
<ListView
SelectionMode="None"
Margin="5,0,10,10"
IsRefreshing="{Binding IsRefreshing}"
HeightRequest="{Binding AltoListaResiduos}"
SeparatorVisibility="None"
HasUnevenRows="true"
ItemsSource="{Binding ListaResiduos}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.ColumnDefinitions>
<!--NOMBRE RESIDUO-->
<ColumnDefinition Width="3*"/>
<!--CANTIDAD ESTIMADA-->
<ColumnDefinition Width="1.5*"/>
<!--NOMBRE ESTIMADA-->
<ColumnDefinition Width="1.5*"/>
<!--CANTIDAD CONTENEDOR-->
<ColumnDefinition Width="1.5*"/>
<!--NOMBRE CONTENEDOR-->
<ColumnDefinition Width="1.5*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding NombreResiduo}"
HorizontalOptions="FillAndExpand"
MaxLines="3"
VerticalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="0"
Margin="4,0">
<Label.FontSize>
<OnPlatform x:TypeArguments="x:Double" iOS="11" Android="11" />
</Label.FontSize>
</Label>
<Label Text="{Binding formattedCantidadEstimada}"
HorizontalTextAlignment="End"
FontSize="Small"
VerticalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="1"
Margin="4,0">
</Label>
<Label Text="{Binding Estimado}"
HorizontalTextAlignment="End"
FontSize="Micro"
VerticalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="2"
Margin="4,0">
</Label>
<Label Text="{Binding CantidadContenedor}"
HorizontalTextAlignment="End"
FontSize="Small"
VerticalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="3"
Margin="4,0">
</Label>
<Label Text="{Binding Contenedor}"
HorizontalTextAlignment="End"
FontSize="Micro"
VerticalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="4"
Margin="4,0">
</Label>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I'm new to Xamarin.Forms and I hope this question helps others, how can I make my list look the same with all the waste? (independent of the name) any help for me?
You shouldn't need the StackLayout at all since you are defining a Grid with the appropriate columns.
This should help your Grid to span properly and fill the entire space
I have a feeling this is happening because you are using VerticalTextAlignment now for some reason both the TextAlignment Properties(H, V) have weird behaviors in them, even though Xamarin says for VerticalTextAlignment that it
Gets or sets the vertical alignment of the Text property.
I would rather use YAlign instead as it does not have this behavior and Xamarin says about YAling that it
Gets or sets the vertical alignment for the Text inside of the Label bound.
Secondly, when you use a grid layout a define the columns and rows you should never use AndExpand types as you have already defined the max area and it will not overlay that. Now what the LayoutOptions docs say is CenterAndExpand or FillAndExpand do is
A LayoutOptions structure that describes an element that is centered and expands.
Also, Remove the StackLayout just keep the Grid in your ViewCell.
<Label Text="{Binding Contenedor}"
XAlign="End"
FontSize="Micro"
YAlign="Center"
TextColor="{StaticResource das.color.texto}"
Grid.Column="4"
Margin="4,0"/>
Want to learn the best practices with Xamarin forms? Check my blog here: https://heartbeat.fritz.ai/techniques-for-improving-performance-in-a-xamarin-forms-application-b439f2f04156

Change a button's image on tap of other button inside a list view, view cell

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!

What is Causing this Exception in Xamarin xaml?

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>

ListView Tapped removes button background color on data template Xamarin.Forms

I don't know why, but when I tap any ListView item, the Button inside it's template loses the background color.
I use default ViewCell inside ListView. Is this a Xamarin.Forms bug?
I have this problem only on iOS.
<ListView x:Name="lv" Grid.Row="2" HasUnevenRows="true" BackgroundColor="White" ItemTapped="OnItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="16" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="{Binding .,Converter={StaticResource IndexColorConverter}">
<StackLayout VerticalOptions="Center">
<Label Text="{Binding Auditorium}" FontSize="18" TextColor="Black"/>
<ContentView Padding="0,-5,0,0">
<Label Text="{Binding Title}" FontSize="16" TextColor="Black"/>
</ContentView>
<StackLayout Orientation="Horizontal">
<Button WidthRequest="100" Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="{Binding ButtonColor}" CommandParameter="{Binding .}" Clicked="Handle_Clicked"/>
<Button WidthRequest="100" Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="{Binding ButtonColor}" CommandParameter="{Binding .}" Clicked="Handle_Clicked" />
</StackLayout>
</StackLayout>
<Label Text="{Binding Coordinator}" FontSize="14" TextColor="Gray"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
There was an old issue that I filed fora similar bug: https://bugzilla.xamarin.com/show_bug.cgi?id=27502.
However, the specific scenario you mention is expected behavior on iOS and happens in native (non-Xamarin.Forms) projects too. See the comment here. You might consider disabling the UITableViewCellSelectionStyle of your cells with UITableViewCellSelectionStyle.None. Here is an example of a cell renderer. You can set the cell.SelectionStyle here. This would stop the gray highlight of the cell. If you don't want that it could be a workaround to keep your button colors.
My workaround for this problem is the following.
<Grid>
<BoxView BackgroundColor="{Binding ButtonColor}"/>
<Button Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="Transparent" CommandParameter="{Binding .}" Clicked="Handle_Clicked"/>
</Grid>

Categories