Improve performance for huge ListBox in StackPanel?

本小妞迷上赌 提交于 2019-12-03 07:43:52

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

eg

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

this will enable the ListBox to load a few items only and will enable a scrollbar on listbox to scroll to rest of the items if needed.

at the same time setting VirtualizationMode to Recycling will help you to reuse the complex data templates thus eliminating the need of re creating them again for every item.


EDIT

here is a solution based on your sample, I have used CompositeCollection with Virtualization to achieve the desired.

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>

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 can not create data template for string so I changed the string collection to Permission collection. I hope in your real project it would be something similar.

give this a try and see if this is close to what you need.

note: you may safely ignore if there is any designer warning on Collection="{Binding DataContext, Source={x:Reference listbox}}"

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!