Improve performance for a huge list in StackPanel?

I use the StackPanel to compose multiple controls vertically (e.g. Title, sub titles, listbox, separator, listbox, etc.).

StackPanel is a child of ScrollViewer to ensure that its contents always scroll.

One of the controls in the StackPanel is the ListBox.

The ItemsSource property is data tied to a huge collection, and the complex DataTemplate is used to implement each item.

Unfortunately, I get very low performance (high processor / memory) with it.

I tried

  • setting the ListBox ItemsPanel to VirtualizationStackPanel and
  • redefinition of its ControlTemplate only in ItemPresenter (remove ListBox ScrollViewer).

But there was no difference in appearances. I assume that the StackPanel gives its inner children infinite height during measurement?

When I replaced ScrollViewer and StackPanel with other panels / layouts (e.g. Grid, DockPanel), and the performance improved significantly, which makes me think that the bottleneck as well as the solution are in virtualization.

Is there a way to improve processor / memory performance in this view?

enter image description here

[Update 1]

Original project example: http://s000.tinyupload.com/index.php?file_id=29810707815310047536

[Update 2]

I tried restyling / templating TreeView / TreeViewItems to give the following example. It still takes a long time to start / same, using high memory. But after loading, the scroll feels much more responsive than the original sample.

I wonder if there is another way to further improve startup / memory usage time?

Restyled TreeView Project: http://s000.tinyupload.com/index.php?file_id=00117351345725628185

[Update 2]

Pushpraj works like a charm

  • Original:
    • Commissioning: 35 seconds,
    • Memory: 393 MB
    • Scrolling: Slow
  • TreeView:
    • Commissioning: 18 s,
    • Memory 377 MB,
    • Scrolling: fast
  • Pushpraj solution:
    • Run: <1s,
    • Memory: 20 MB,
    • Scrolling: fast
+5
source share
1 answer

perhaps you can limit the maximum size of the huge list and enable Virtualization

eg,

 <ListBox MaxHeight="500" VirtualizingPanel.IsVirtualizing="true" VirtualizingPanel.VirtualizationMode="Recycling" /> 

this will allow the ListBox to load only a few items and will include a scroll bar in the list to scroll to the rest of the items, if necessary.

at the same time, installing VirtualizationMode in Recycling will help you reuse complex data patterns, thereby eliminating the need to re-create them for each element.


EDIT

here is a solution based on your sample, I used CompositeCollection with Virtualization to achieve what I wanted.

Xaml

 <Grid xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:l="clr-namespace:PerfTest"> <Grid.Resources> <DataTemplate DataType="{x:Type l:Permission}"> <StackPanel Orientation="Horizontal"> <CheckBox /> <TextBlock Text="{Binding Name}" /> <Button Content="+" /> <Button Content="-" /> <Button Content="..." /> </StackPanel> </DataTemplate> <CompositeCollection x:Key="data"> <!-- Content 1 --> <TextBlock Text="Title" FontSize="24" FontWeight="Thin" /> <!-- Content 2 --> <TextBlock Text="Subtitle" FontSize="16" FontWeight="Thin" /> <!-- Content 3 --> <CollectionContainer Collection="{Binding DataContext, Source={x:Reference listbox}}" /> <!-- Content 4 --> <TextBlock Text="User must scroll past the entire list box before seeing this" FontSize="16" FontWeight="Thin" Padding="5" TextWrapping="Wrap" Background="#99000000" Foreground="White" /> </CompositeCollection> </Grid.Resources> <ListBox x:Name="listbox" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{StaticResource data}" /> </Grid> 

the code

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var items = new ObservableCollection<Permission>(); foreach (var i in Enumerable.Range(0, 10000).Select(i => new Permission() { Name = "Permission " + i })) { items.Add(i); } DataContext = items; } } public class Permission { public string Name { get; set; } } 

since we cannot create a data template for a row, so I changed the row collection to the Permission collection. I hope that in your real project it will be something similar.

try and make sure that it is close to what you need.

Note: you can safely ignore if there is a constructor warning on Collection="{Binding DataContext, Source={x:Reference listbox}}"

+9
source

Source: https://habr.com/ru/post/1201239/


All Articles