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

查看:87
本文介绍了提高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是绑定到庞大集合的数据,并且使用复杂的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.

我尝试了

  • 将列表框的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?

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

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/内存性能?

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
    • 滚动:缓慢
    • Original:
      • Startup: 35s,
      • Memory: 393MB
      • Scrolling: Slow
      • 启动时间:18秒,
      • 内存377MB,
      • 滚动:快速
      • 启动:< 1s,
      • 内存:20MB,
      • 滚动:快速

      推荐答案

      您可能会限制巨大列表框的最大大小并启用Virtualization

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

      例如

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

      同时将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天全站免登陆