如何加快ListBox渲染和ListCollectionView过滤?

时间:2011-06-21 08:48:05

标签: c# wpf xaml optimization filtering

这里有一个双管齐下的问题,但我认为这两个问题足够紧密,需要将它们包含在一起。

在我们的应用程序中,我们有一个ListBox,其中填充了大量项目。这些项目中的每一项都显示有相当复杂的项目模板。它必然相当复杂,虽然它可能会被削减一点,但我可能不会花费很多钱。 ListBox中的项目来自ListCollectionView,该ObservableCollection<>是根据要显示的ListCollectionView个对象构建的。

我们有两个问题。

首先,当我们为Refresh重新配置过滤器并在其上调用ListBox时,在用户界面被拆除并重新创建时,会有非常明显的几秒钟锁定,并且ListBox重新填充。此锁定的持续时间似乎与ListBox中包含的元素数量相关,并且在ListCollectionView的客户区域中充满项目时最长。我们非常肯定锁定是由重新创建的项目模板引起的。我尝试过打开虚拟化,但这对减少或消除减速没有任何影响。我还在研究其他一些优化,比如检查我们的绑定和修改布局。是否有任何方法可以避免这个特定问题,加快速度,或将其移动到不同的线程? (我知道最后一个是非常不可能的,因为渲染都是单线程的,但也许有一些解决方法......)

第二个涉及对ListCollectionView的过滤。虽然目前这不是一个问题,但我们认为过滤有可能成为一个问题并导致UI线程明显锁定。我正在努力减少过滤开销,但我想知道是否有一种方法可以将ListCollectionView上的Refresh调用移到另一个线程上?到目前为止,我的尝试都没有成功,似乎是因为{{1}}不会自动将某些事件封送到正确的线程上。

指出或解释这两个问题的任何已知或潜在解决方案将非常有帮助。

3 个答案:

答案 0 :(得分:2)

关于数据网格渲染和绑定的this SO线程中的一些有趣的想法 - 您也可以将它们应用到列表框场景中......

答案 1 :(得分:2)

我认为你不能同时虚拟化和过滤。所以,如果我在你的鞋子里,我会坚持使用虚拟列表框并在另一个线程中执行过滤逻辑。当然,您可能必须编写一些之前已经编写过的代码,但是如果它没有锁定您的GUI?值得。

答案 2 :(得分:1)

来自here的2个提示,第一个有助于虚拟化ListBox

使用VirtualizingStackPanel作为ItemsPanel列表来虚拟化列表和视图。这仅在加载时创建可见元素。所有其他元素在可见时都是惰性的。请注意,分组或CanContentScroll="True"会阻止虚拟化!

启用容器回收。虚拟化带来了许多性能改进,但容器将被处理并重新创建,这是默认设置。但是,您可以通过设置VirtualizingStackPanel.VirtualizationMode="Recycling"

来回收容器,从而获得更高的性能

我通过here on codeproject描述的技术对我庞大的对象列表进行了虚拟化,效果很好