问题 为什么ObservableCollection不支持批量更改?


什么是由...造成的潜在问题 ObservableCollection 支持等业务 AddRange 要么 RemoveRange?由于ObservableCollection经常与WPF一起使用,因此必须有微软没有提供它们的原因。

您可以实现自己的集合,支持批量操作和实现 INotifyCollectionChanged。如果我将这样的控件绑定到ItemsControl会发生什么?

有谁知道不支持批量更改的ItemsControls?


7140
2018-03-05 17:05


起源

Microsoft.VisualStudio.Language.Intellisense.BulkObservableCollection <T>中有一个BulkObservableCollection类。 msdn.microsoft.com/en-us/library/dd867973.aspx - tofutim


答案:


我不认为有任何潜在的缺点或问题,只是它不存在。实际上,您会发现'System.Collections.Generic'中的大多数类型也不提供'AddRange'功能。

同时,很多人创建了自己的'ObservableCollection'版本,以提供您想要的功能。 INotifyCollectionChanged包含足够的信息供其处理程序记录,因为这个原因可能会影响一系列项目。

最后但并非最不重要的是,如果您绑定具有这些“范围”类型操作的集合,您会发现它们将按预期使用您的UI


3
2018-03-05 17:20





有很多扩展 ObservableCollection 可以在互联网上找到添加/删除范围的概念,或允许您推迟更新并手动触发它们。例如,请参阅此Stack Overflow问题:

ObservableCollection不支持AddRange方法,因此除了INotifyCollectionChanging外,我还会收到添加的每个项目的通知?

您还可以实现触发重置事件的批量添加,这将导致UI重新呈现集合中的所有项目:

http://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/

这些允许您更有效地管理UI更新。怎么样 ItemsControl 处理集合更改事件,详细说明已更改项目的列表由WPF框架本身决定。我假设它智能地处理这个!

我的建议是,如果性能对您至关重要,并且您的集合中有许多项目正在更新并且遇到性能问题,那么子类 ObservableCollection 以最适合您的应用程序需求的方式管理集合更改通知。


4
2018-03-05 17:10



快速浏览一下链接问题的实现就会显示效率低下。基本上, CollectionChanged 为每个添加的项目引发事件,然后再次重置集合! - Kent Boogaart
@KentBoogaart嗨肯特,你的意思是答案吗?看起来很好。 AddRange方法迭代添加的项,然后触发单个CollectionChanged事件,更改类型为“add”,提供添加项的列表。虽然代码格式不是很好;-) - ColinE
由于RangeObservableCollection扩展了ObservableCollection,因此在每个项目上调用Add会导致为每个添加的项目引发CollectionChangedEvent。然后,在添加所有项目之后重置集合,所有这些努力都会浪费。 - Kent Boogaart
除非它没有,因为链接的代码也会覆盖OnCollectionChanged以在设置标志时禁止CollectionChangedEvent; AddRange方法设置此标志,循环并为每个项调用Add,然后取消设置标志。 - Chris


NotifyCollectionChangedEventArgs 包括索引信息。删除项目会导致索引重新洗牌,插入项目也是如此。因此,虽然并非完全不可能,但提供使用范围的能力将相当困难并且可能效率低下。


2
2018-03-05 17:10



唯一的索引信息是“发生更改的索引”。通过添加和删除范围操作可以轻松提供此信息。 - A.R.
@ A.R。:nope,如果我删除该集合的第一个和最后一个项目该怎么办?事件args中只有一个索引,但是需要两个索引。 - Kent Boogaart
有两个索引。有'NewStartingIndex'和'OldStartingIndex'。后者的描述为“获取发生移动,移除或替换操作的索引。”,此外,除非您要删除集合中的所有项目,否则您描述的方案是不可能的,因为范围中的元素是连续的。 - A.R.
我的坏 - 我误读了OP。我认为这个问题是为什么没有 RemoveAll,就像有 List<T>。你是对的: AddRange/RemoveRange 很容易提供。 - Kent Boogaart


必须有一个理由为什么微软不提供它们

它们并不提供所有可能的功能,它(也)是成本与需求的关系。

您可以实现自己的集合,支持批量操作和实现 INotifyCollectionChanged

是。当你这样做时,你会发现该集合必须选择如何/何时传播这些变化。我从未尝试过,但我想有一些权衡,View或ViewModel可以做出比可重用集合更好的决策。


1
2018-03-05 17:11