MAUI: Header in Colectionview not displayed when layout is inserted - c#

I am trying to show a header in my collectionview with this code (which im sure would work on xamarin)
<CollectionView SelectionMode="Multiple"
SelectionChanged="collectionview_coll_skills_SelectionChanged"
Margin="5,0,0,0"
EmptyView="{x:Static res:Strings.LaedtSKills}"
Grid.Row="0"
VerticalScrollBarVisibility="Never" x:Name="collectionview_coll_skills">
<CollectionView.HeaderTemplate>
<DataTemplate>
<ViewCell>
<ContentView>
<Label Text="Hi mom"/>
</ContentView>
</ViewCell>
</DataTemplate>
</CollectionView.HeaderTemplate>
The text "hi mom" is just not shown at all,
if I however inserted the text directly into the property (eg Header="hi mom")
It would be displayed but then no layoutting is possible.
Anyone already found a fix or workaround for this?
Thanks

As posted in my comment you can just use the Header of the CollectionView
You can style it as needed. More Info Microsoft Header/Footer resource
<CollectionView.Header>
<Label Text="Hi mom" />
</CollectionView.Header>

Related

How can I optimize listview data binding in .NET MAUI?

I am working on a MAUI app, which has a page with two ListViews. Only one should be visible at a time, which i do by setting their IsVisible property to true or false. Upon switching from one to the other, the app freezes or becomes extremely slow. I suppose this is because the listview's itemssource is rather large. I bound both listviews to an observablecollection, which should be the fastest option. Both ObservableCollections have data that updates rather often, and both should get quite big (1000+ items).
How can I optimize the listviews to load quickly?
I have tried to limit the itemssource to a certain amount of objects, but this only makes it slower. I guess this is because removing items from the itemssource in a first-in-first-out way basically updates every single object within the obervablecollection.
My current code:
`
<Grid RowDefinitions="*,5,40" ColumnDefinitions="75,75,75,105,*">
<ScrollView x:Name="SerialLogScrollViewASCII"
Grid.ColumnSpan="6"
VerticalScrollBarVisibility="Always"
Grid.Row="0"
IsVisible="{Binding IsASCIILogVisible}"
BackgroundColor="Transparent">
<ListView x:Name="LogStackASCII"
ItemsSource="{Binding SerialLogASCII}"
BackgroundColor="Transparent"
ItemTapped="LogMessageTapped"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate >
<ViewCell>
<Grid PropertyChanged="SerialLogChanged" ColumnDefinitions="160,*" ColumnSpacing="5" BackgroundColor="Transparent">
<Label Text="{Binding Time}" Margin="0,0,10,0" Grid.Column="0" FontSize="12" BackgroundColor="Transparent"/>
<Label Text="{Binding Message}" LineBreakMode="CharacterWrap" Grid.Column="1" FontSize="12" BackgroundColor="Transparent"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
<ScrollView x:Name="SerialLogScrollViewHEX"
Grid.ColumnSpan="6"
VerticalScrollBarVisibility="Always"
Grid.Row="0"
IsVisible="{Binding IsHEXLogVisible}"
BackgroundColor="Transparent">
<ListView x:Name="LogStackHEX"
ItemsSource="{Binding SerialLogHEX}"
BackgroundColor="Transparent"
ItemTapped="LogMessageTapped"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate >
<ViewCell>
<Grid PropertyChanged="SerialLogChanged" Padding="1" ColumnDefinitions="160,*" ColumnSpacing="5" BackgroundColor="Transparent">
<Label Text="{Binding Time}" Margin="0,0,10,0" Grid.Column="0" FontSize="12" BackgroundColor="Transparent"/>
<Label Text="{Binding Message}" LineBreakMode="CharacterWrap" Grid.Column="1" FontSize="12" BackgroundColor="Transparent"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</Grid>
`
When you put Vertical ListView, inside Vertical ScrollView, the performance is pretty much non-existent. The more and more items you add, the worse it will get.
You should not be doing this. ListView has its own scroll.
Consider CollectionView or DataGrid.
First remove the scolls. Then if you are not happy, try CollectionView or DataGrid.
And then if you have questions, please ask.
Edit: Last attempt to explain this.
Putting a ListView or CollectionView or ANY container that has variable height, inside Vertical ScrollView or Vertical StackLayout or ANY container that is not limiting the height, makes the first container GROW in height until all the content is loaded.
This means, if you have 100 000 items, all of them will be loaded in the inner container.
This "programmatically scrolling works better" is actually the result of pre-loading everything, and it is not better for the performance, it is plain and simple killing it.
Try adding 100, 1000, 10000, 100000 items, and you will see how it gets progressively worse.
Containers of other VisualElements (Like ListView or CollectionView) have built-in design patterns to handle displaying them in portions. When and if displaying of that item is needed.
You could try Caching strategy in ListView. Try the following code
<ListView x:Name="LogStackASCII" CachingStrategy="RecycleElement"
...
RecycleElement should be used in the following circumstances:
Each cell has a small to moderate number of bindings.
Each cell's BindingContext defines all of the cell data.
Each cell is largely similar, with the cell template unchanging.
I found the Xamarin official docs ListView performance for you. It also works for Maui. Besides the Caching strategy, it also gives some other ListView performance suggestions to enhance performance of Listview.
By the way, the two ListView almost have the same template, so why not just use one ListView? And when switching, just change the itemsSource it binds to.
Hope it works for you.

Empty view in list View in xamarin

I have a list view in my xamarin app and I need to put an option that when the list is empty, in the collection view we have <CollectionView.EmptyView> but when I search for list view there is no option for it and it's more complex, so, there is a quick fix or not? and what is the there standard solution for it ?
Actually,CollectionView is a better choice for empty view.However, if you insist on using listivew to achieve empty view effect,you could use this package Syncfusion.Xamarin.SfListView.Just binding IsVisible property when the listview is empty like below,for more details please refer to this repo.
<Grid>
<Button x:Name="ItemSource" Grid.Row="0"
Text="Change ItemSource"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Command="{Binding ChangeItemsSource}"/>
<Grid IsVisible="{Binding IsVisible}" Grid.Row="1">
<Label x:Name="label"
Text = "No Items :(" />
</Grid>
<sync:SfListView x:Name="listView" Grid.Row="1"
ItemsSource="{Binding ContactsInfo}"
IsVisible="{Binding Path=IsVisible, Converter={StaticResource visibilityConverter}}"
ItemSize="30">
<sync:SfListView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding ContactName}"/>
</DataTemplate>
</sync:SfListView.ItemTemplate>
</sync:SfListView>
</Grid>
Official reference link:https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/emptyview

strings randomly cut off in xamarin listview

I'm making a basic Android master/detail app in VS 2019, which was started with the "Blank" mobile template.
I'm just using a grid for the layout. I have the ListView in a frame, which is in a row of the grid. The ItemsSource of the ListView is bound to a generic List:
List<MyObject>
The MyObject class has a Name property. The ListView contains a simple Label in its ViewCell/DataTemplate/ItemTemplate. The Text of the Label is bound to the Name property of the MyObject class.
The problem is that some of the strings displayed are cutoff. Which strings are cutoff seems random. When I tap a row, a Details page is displayed for the item in the tapped row. When I do that and then hit Back, some of the strings that were cutoff are now fully displayed, while other entries either remain cutoff and/or there are entries that were not cutoff, but are now cutoff.
The pic at the link below shows 2 screen shots. The one on the left is before opening the Details page, and the other is after returning from the Details page:
2 screen shots; left is before Details page displayed, the right after
I'm fairly new to Xamarin Forms, so I'm probably missing something basic. The randomness of which entries are cutoff really has me puzzled. Any help would be appreciated.
Here's the XAML for the Frame and ListView:
<!-- items list -->
<Frame x:Name="ListFrame"
Grid.Row="3"
VerticalOptions="Fill"
HorizontalOptions="Fill"
OutlineColor="Black"
Padding="5"
Margin="4"
>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedCryptoItem}"
IsRefreshing="{Binding IsRefreshingList}"
RefreshCommand="{Binding RefreshListCommand}"
ItemSelected="OnItemSelected"
CachingStrategy="RecycleElement"
VerticalScrollBarVisibility="Always"
RowHeight="24"
IsPullToRefreshEnabled="True"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"
LineBreakMode="NoWrap"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="StartAndExpand"
VerticalOptions="CenterAndExpand"
/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
Looking to your code, VerticalOptions and HorizontalOptions are not optimized and can be buggy (regarding cells recycling with different texts ?).
You should use HorizontalTextAlignment and VerticalTextAlignment like advised here https://kent-boogaart.com/blog/jason-smith%27s-xamarin-forms-performance-tips. The Label Control will then use the entire space and text will be aligned as you want.
Later, you will probably embedd this Label in a Grid or another Layout if you want a more complex cell (with several controls)

How to data bind a ListView item to an item in a structured list with multiple indexes?

I'm attempting to data bind a list of information to a ListView in Xamarin.forms, but I'm having issues because of how it is indexed. I need to get the string of information found in sortedList[0].Info[multiple indexes].CoverLink to display on my Image element inside of my Xamarin app, but I'm not sure how to go about it. My Xaml file is as follows:
<ListView RowHeight="100" x:Name="PinnedListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="Start">
<Image Source="{Binding CoverLink}" HeightRequest="100"/>
<StackLayout Orientation="Vertical">
<Label Text="{Binding ID}"/>
<Label Text="{Binding SomeOtherBinding}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and I'm assigning the ItemSource via c# by stating:
PinnedListView.ItemsSource = sortedList;
Here is a screenshot of my list architecture:
How to data bind it? Thanks.
you need to specify which element of the Info array you want to use
<Image Source="{Binding Info[0].CoverLink}" HeightRequest="100"/>
As you can see, the CoverLink is in the Infonested array, so, in order to access to it try this:
<Image Source="{Binding Info[0].CoverLink}" HeightRequest="100"/>

Custom viewcell like imagecell xaml?

How would i go about creating an identical "imagecell" but custom? The problem i am having with regular "imagecell" is that the image is hardcoded to 60x60 ..
I am pulling favicon from url's which means that a favicon from 16x16 to 60x60 will have super low quality. The alternative i have here is to change the size of the image but yet again, not doable in "imagecell" as it is hard coded.
Is there any website with different custom cells that i can look on or do anyone have the code for an identical imagecell view.
this is the code i am currently using.
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding mainSite}" TextColor="Black" Detail="{Binding link}" ImageSource="{Binding image}"></ImageCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
you could easily build a similar UI with a ViewCell using nested StackLayouts, or alternatively a Grid
<StackLayout Orientation="Horizontal">
<Image />
<StackLayout>
<Label />
<Label />
</StackLayout>
</StackLayout>

Categories