WPF的ICollectionView.filter包含大量数据

J W*_*J W 24 c# wpf listview filter

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

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

private bool FilterCallback(object item)
{
  //Filter logic
}
Run Code Online (Sandbox Code Playgroud)

但是这会在UI线程中运行并在过滤时阻止整个应用程序,这会给用户带来非常糟糕的体验.所以我向大家提出的问题是:有没有人知道在wpf中过滤listview的"更好"的方式,还是应该过滤底层代码ObservableCollection

Bry*_*son 21

密切关注您的过滤功能.确保您没有进行任何不必要的装箱/拆箱,并且您没有进行大量计算.你还应该注意你正在使用哪种CollectionView,有些比其他更快.来自Bea关于排序的帖子:

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

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

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

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

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

  • @Bryan:我有类似的情况,我想提高我的过滤器性能.你在答案中写道,应该避免使用`Predicate <object>`因为它需要装箱/拆箱操作而不包括返回类型.你到底是什么意思?它的返回类型为`bool`,它必须是`Predicate <object>`因为`ListCollectionView`的`Filter`属性是这样定义的.有没有办法绕过这个并使用另一种过滤方法?或者你的意图是什么?也许我只是误解了它...... (6认同)
  • 您能否添加一些示例代码来说明如何将过滤移动到其他线程?我似乎无法在不同的线程上工作. (2认同)