【问题标题】:WPF: what's the most efficient/fast way of adding items to a ListView?WPF:将项目添加到 ListView 的最有效/快速的方法是什么?
【发布时间】:2010-07-22 02:33:58
【问题描述】:

我需要在以相当高的频率添加的网格中显示大量行(在某些情况下最多每秒 10 行) 我选择 ListView 是因为我认为它是 WPF 中最快的网格控件。 (肯定比 GridView 快很多)

在添加了几十万个项目之后,CPU 利用率变得相当高,并且它们继续进入。这相当令人惊讶,因为 ListView 只呈现可见行,因此总共添加了多少行并不重要。

我的第一个方法是将它绑定到 ObservableCollection,但过了一段时间,CPU 利用率上升,整个窗口变得紧张。

我尝试将它绑定到一个常规列表,这似乎更快,但是我确实需要经常调用列表上的 .Refresh() ,这在一段时间后也会猛烈抨击 CPU。

我尝试subclassing ObservableCollection 对插入进行分块,希望对它们进行批处理可以提高性能/减少 cpu 工作量,但这种方法似乎需要调用 CollectionView.Refresh,这与在集合上调用 Reset() 相同,而且效率低下当集合中有很多项目时。

清除 observablecollection 并调用 myListView.Items.Refresh() 将其降低到 0 会使 CPU 使用率回到起点。

这里开始没有想法了.. 同样,我的目标是添加/显示大量项目并以最高效的方式显示 8 列网格.. ListView 看起来不错,只是必须有一些方法我可以进一步调整它..

更新

分析后,ObservableCollection 800k 行在网格中,cpu 最密集的工作由:

  • (75%) System.Windows.Media.MediaContext.RenderMessageHandler(object resizedCompositionTarget)
  • (20%) ObservableCollection.OnCollectionChanged(NotifyCoolectionChanged..)

虽然根据会话这些数字差异很大..

UPDATE 2 .. 好的 BindingList 显然是这里的赢家。

这是并排显示的结果(以刻度为单位),每行有 100 万行(每秒添加 10 个项目):

可观察集合: http://i.imgur.com/7ZoSv.png

绑定列表 http://i.imgur.com/jm5qF.png

您可以看到 CPU 活动的总体下降,以及在 Binding List 案例中处理树所需的大约一半的滴答声!感谢 Akash 提出的这个好主意。

【问题讨论】:

    标签: wpf performance


    【解决方案1】:

    我会建议使用 BindingList 类,而不是使用 ObservableCollection,你可以这样做......

    BindingList<string> list = new BindingList<string>();
    
    list.AllowEdit = true;
    list.AllowNew = true;
    list.AllowRemove = true;
    
    // set the list as items source
    itemCollection.ItemsSource = list;
    
    // add many items...
    
    // disable UI updation
    list.RaiseListChangedEvents = false;
    
    for each(string s in MyCollection){
       list.Add(s);
    }
    
    // after all.. update the UI with following
    list.RaiseListChangedEvents = true;
    list.ResetBindings(); // this forces update of entire list
    

    您甚至可以分批启用/禁用更新,而不是一次性添加所有内容,BindingList 在我所有的 UI 中都比 ObservableCollection 运行得更好,我想知道为什么当 BindingList 真正取代 ObservableCollection 时,人们更多地谈论 ObservableCollection。

    【讨论】:

    • Akash,谢谢。我将很快测试这个集合。我很好奇的一件事是,是否有办法在不刷新整个列表的情况下进行批量插入。我相信这是很多抖动和 cpu 工作的来源,当刷新 800k 项目等时。
    • 我不认为它会刷新 800k 个项目,因为虚拟化面板只会刷新屏幕上的有限项目。但是另一种方法是使用某种寻呼机对您的项目进行分页,在我的应用程序中,我只首先加载 0-20 并让用户逐个导航,他们也可以使用某种搜索进行过滤
    • 你试过过滤你的绑定列表吗?对于 ObservableCollection,我使用的是 CollectionViewSource,因为它提供了一个过滤器,该过滤器在每个添加的项目上执行。该过滤器可能会在刷新后对所有行执行。所以我需要找到另一种添加过滤的方法。
    • 对不起,我想过滤是不可能的,但你可以尝试过滤 UI,ItemsControl 的 ItemsCollection 确实允许过滤,你也可以在加载时从模型中过滤数据,然后将其传递给控件。
    • 您也可以创建自己的绑定列表版本,您必须使一个类派生或包含任何列表并实现 IBindingList 接口!以获得出色的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多