WPF 的 ICollectionView.filter 与大量数据集

Posted

技术标签:

【中文标题】WPF 的 ICollectionView.filter 与大量数据集【英文标题】:WPF's ICollectionView.filter with large sets of data 【发布时间】:2010-10-25 11:48:07 【问题描述】:

我正在开发一个 wpf 应用程序,其中包含一个包含大量数据(10 000 到 100 000)行的列表视图。用户可以将各种过滤器应用于此列表视图,从而使过滤器逻辑非常先进(而且速度很慢)。目前,我的代码的相关部分如下所示:

ICollectionView view = CollectionViewSource.GetDefaultView(hugeList.ItemsSource);
view.Filter = new Predicate<object>(FilterCallback);

private bool FilterCallback(object item)

  //Filter logic

但这在 UI 线程中运行并在过滤时阻塞了整个应用程序,这给用户体验带来了非常糟糕的体验。所以我对你们所有人的问题是:有人知道在 wpf 中过滤列表视图的“更好”方法还是应该过滤底层的ObservableCollection

【问题讨论】:

+1 好问题!你想出了什么解决方案? 性能问题可能出在网格绑定/渲染方面,与实际过滤器逻辑无关... 【参考方案1】:

密切注意您的过滤功能。确保您没有进行任何不必要的装箱/拆箱,并且您没有在其中进行大量计算。您还应该注意您使用的是哪种 CollectionView,有些比其他更快。来自Bea's post on sorting:

如果您的源实现 IEnumerable,则会创建一个 CollectionView。如果源实现了 IEnumerableonly,您将无法对集合进行排序或分组(您只能对其进行过滤)。此外,如果源具有大量项目或执行动态操作(例如插入和删除),则 perf 不会是最好的。如果这是您的方案,您应该考虑让您的源实现更强大的接口。 ICollection 稍微好一点,因为它提供了一个 Count 属性。

ListCollectionView是源实现IList时创建的视图类型。与 IEnumerable 和 ICollection 相比,IList 对于大型或动态列表的性能要好得多,因为它提供了一个索引器,允许我们快速随机访问。此外,IList 允许排序、分组和过滤。但理想情况下,您的源集合源自 ObservableCollection,它是数据绑定眼中所有集合之母,因为它提供了一些额外的好处,例如属性和集合更改通知。

BindingListCollectionView是Avalon在源集合实现IBindingList时创建的视图类型。这是我们在 ADO.NET 场景中处理的视图。它支持排序和分组,但不支持传统的过滤。相反,它有一个额外的 CustomFilter 属性,将过滤委托给 DataView(有关详细信息,请参阅我在 ADO.NET 上的帖子)。

您可以像@mihi 所说的那样将过滤踢到不同的线程,但我已经使用 CollectionViews 在 ObservableCollection 上同时运行多个过滤器,对象上有约 60 个变量(数据库表中的列)有 50,000 个项目,没有明显的滞后。

我在您的过滤器函数中立即注意到的一件事是输入是 Object 类型,这可能意味着您正在函数内进行类型转换,并且可能不需要。您还使用不包含返回类型的 Predicate,因此可能需要在 CollectionView 的过滤方法中进行一些类型转换或反射,并且可能会减慢您的速度。

【讨论】:

能否添加一些示例代码来展示如何将过滤移至不同的线程?我似乎无法让它在不同的线程上工作。 @Bryan:我有类似的情况,我想提高我的过滤器性能。您在回答中写道,应该避免使用Predicate&lt;object&gt;,因为它需要装箱/拆箱操作并且不包括返回类型。你到底是什么意思?它的返回类型为bool,它必须是Predicate&lt;object&gt;,因为ListCollectionViewFilter 属性就是这样定义的。有没有办法解决这个问题并使用另一种过滤方法?或者你的意图是什么?可能是我误会了…… @gehho 我想我当时只是为了可能导致减速的事情抛出想法。 100 次中有 99 次会导致问题的过滤逻辑变慢。【参考方案2】:

您是否考虑过在另一个线程中过滤或使用调度程序?

WPF Threads: Build more responsive apps with the dispatcher 为您提供了一些可用的线程选项的概览。

【讨论】:

我已经考虑过了,但我无法在与 UI 线程不同的线程中访问“ICollectionView”? 否,但您可以在另一个线程中执行过滤逻辑并使用 Dispatcher.Invoke 在 UI 线程上修改集合 这里是这个解决方案的一个很好的例子:codeproject.com/Articles/32426/…

以上是关于WPF 的 ICollectionView.filter 与大量数据集的主要内容,如果未能解决你的问题,请参考以下文章

【WPF】wpf加载和保存xaml文件

wpf 添加动态图片

wpf和winform的区别

wpf 用啥字体

wpf是啥

winform 可以用wpf窗体吗