C# 带有大量数据的 WPF 的 ICollectionView.filter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/851545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:10:39  来源:igfitidea点击:

WPF's ICollectionView.filter with large sets of data

c#wpflistviewfilter

提问by J W

I'm working on an wpf app which contains a listview with quite a lot of data (10 000 to 100 000) rows. The user can apply all sorts of filters to this listview making the filter logic quite advanced (and slow). For now, the relevant part of my code looks like this:

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

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

private bool FilterCallback(object item)
{
  //Filter logic
}

But this runs in the UI thread and blocks the entire application when filtering which gives a very poor user experience. So my question to you all is: does anyone know a 'better' way to filter a listview in wpf or should I filter the underlying ObservableCollectioninstead?

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

采纳答案by Bryan Anderson

Pay close attention to your filter function. Make sure you aren't doing any unnecessary boxing/unboxing and you aren't doing extensive calculations in it. You should also pay attention to which kind of CollectionView you're using, some are faster than others. From Bea's post on sorting:

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

  • A CollectionViewis created if your source implements IEnumerable. If the source implements IEnumerable only, you will not be able to sort or group the collection (you can only filter it). Also, perf will not be the best if the source has a large number of items or if you perform dynamic operations such as insertions and deletions. If this is your scenario, you should consider having your source implement a stronger interface. ICollection is slightly better because it provides a Count property.

  • ListCollectionViewis the view type created when the source implements IList. Compared to IEnumerable and ICollection, IList performs much better for large or dynamic lists because it provides an indexer, allowing us quick random access. In addition, IList allows sorting, grouping and filtering. But ideally your source collection derives from ObservableCollection, the mother of all collections in the eyes of data binding, since it provides several extra goodies such as property and collection change notifications.

  • BindingListCollectionViewis the type of view created by Avalon when the source collection implements IBindingList. This is the view we deal with in the ADO.NET scenario. It supports sorting and grouping, but not traditional filtering. Instead, it has an additional CustomFilter property that delegates filtering to the DataView (see my post on ADO.NET for more details).

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

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

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

You can kick the filtering to a different thread as @mihi said but I have used CollectionViews to run multiple filters concurrently on an ObservableCollection with 50,000 items on an object with ~60 variables (columns in a database table) without noticeable lag.

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

One thing I notice immediately in your filter function is the input is of type Object which likely means you're doing a type conversion within the function and may not need to. You also use Predicate which doesn't include a return type so that probably requires some type conversions or reflection within the CollectionView's filtering methods and might slow you down as well.

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

回答by user103712

Have you considered filtering in another thread or using the dispatcher?

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

WPF Threads: Build more responsive apps with the dispatchergives you a nice overview of some of the threading options available to you.

WPF 线程:使用调度程序构建响应速度更快的应用程序让您可以很好地概述一些可用的线程选项。