提高 StackPanel 中巨大 ListBox 的性能? [英] Improve performance for huge ListBox in StackPanel?

查看:26
本文介绍了提高 StackPanel 中巨大 ListBox 的性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 StackPanel 垂直布局多个控件(即标题、子标题、列表框、分隔符、列表框等).

I am using a StackPanel to layout several controls vertically (ie, Title, sub titles, listbox, separator, listbox, etc).

StackPanel 是 ScrollViewer 的子项,以确保其内容始终可滚动.

The StackPanel is a child of a ScrollViewer to ensure its content is always scrollable.

StackPanel 中的一个控件是 ListBox.

One of the controls in the StackPanel is a ListBox.

它的ItemsSource是绑定在一个庞大集合上的数据,每个item都是用一个复杂的DataTemplate来实现的.

Its ItemsSource is data bound to a huge collection, and a complex DataTemplate is used to realise each item.

不幸的是,我的性能真的很差(高 CPU/内存).

Unfortunately, I'm getting really poor performance (high cpu/memory) with it.

我试过了

  • 将 ListBox 的 ItemsPanel 设置为 VirtualizingStackPanel,并且
  • 仅将其 ControlTemplate 覆盖为 ItemsPresenter(删除 ListBox 的 ScrollViewer).

但是在性能上没有区别.我猜 StackPanel 在测量期间会为其内部子级提供无限高度?

But there were no difference in performances. I'm guessing the StackPanel gives its internal children infinite height during measure?

当我将 ScrollViewer 和 StackPanel 替换为其他面板/布局(例如 Grid、DockPanel)并且性能显着提高时,我相信瓶颈和解决方案都在虚拟化中.

When I replaced the ScrollViewer and StackPanel with other panels/layouts (e.g, Grid, DockPanel) and the performance improves significantly, which leads me to believe the bottleneck, as well as solution, is in virtualization.

我有什么办法可以提高这个视图的 cpu/memory 性能吗?

Is there any way for me to improve the cpu/memory performance of this view?

[更新 1]

原始示例项目:http://s000.tinyupload.com/index.php?file_id=29810707815310047536

[更新 2]

我尝试重新设计/模板化 TreeView/TreeViewItems 以提出以下示例.仍然需要很长时间才能启动/相同,内存使用率很高.但是一旦加载,滚动感觉比原始示例响应更快.

I tried restyling/templating TreeView/TreeViewItems to come up with the following example. It still takes a long time to start/same,high memory usage. But once loaded, scrolling feels a lot more responsive than the original sample.

想知道是否还有其他方法可以进一步提高启动时间/内存使用率?

Wonder if there's any other way to further improve the start up time/memory usage?

重新设计的 TreeView 项目:http://s000.tinyupload.com/index.php?file_id=00117351345725628185

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

[更新 2]

pushpraj 的解决方案就像一个魅力

pushpraj's solution works like a charm

  • 原文:
    • 启动:35 秒,
    • 内存:393MB
    • 滚动:慢
    • 启动时间:18 秒,
    • 内存 377MB,
    • 滚动:快速
    • 启动:<1s,
    • 内存:20MB,
    • 滚动:快速

    推荐答案

    你可能会限制巨大列表框的最大尺寸并启用虚拟化

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

    例如

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

    这将使 ListBox 仅加载几个项目,并在需要时启用列表框上的滚动条滚动到其余项目.

    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.

    同时将 VirtualizationMode 设置为 Recycling 将帮助您重用复杂的数据模板,从而无需为每个项目重新创建它们.

    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.

    编辑

    这里是基于您的示例的解决方案,我使用 CompositeCollectionVirtualization 来实现所需的.

    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>
    

    代码

    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; }
    }
    

    由于我们无法为字符串创建数据模板,所以我将字符串集合更改为 Permission 集合.我希望在你的实际项目中会是类似的.

    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.

    注意:如果 Collection="{Binding DataContext, Source={x:Reference listbox}}" 上有任何设计器警告,您可以放心地忽略

    这篇关于提高 StackPanel 中巨大 ListBox 的性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆