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

Time:12-29

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>

`

CodePudding user response:

  1. 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.

  1. 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.

CodePudding user response:

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:

  1. Each cell has a small to moderate number of bindings.
  2. Each cell's BindingContext defines all of the cell data.
  3. 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.

  • Related