【问题标题】:Why does ObservableCollection not support bulk changes?为什么 ObservableCollection 不支持批量更改?
【发布时间】:2012-03-23 04:04:48
【问题描述】:

ObservableCollection 支持AddRangeRemoveRange 等操作会导致哪些潜在问题?既然 ObservableCollection 如此频繁地与 WPF 一起使用,Microsoft 没有提供它们一定是有原因的。

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

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

【问题讨论】:

标签: c# wpf observablecollection


【解决方案1】:

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

与此同时,许多人创建了自己的“ObservableCollection”版本来提供您想要的功能。 INotifyCollectionChanged 包含足够的信息,供其处理程序记录一系列项目何时可能因此受到影响。

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

【讨论】:

    【解决方案2】:

    ObservableCollection 的许多扩展可以在 Internet 上找到,它们添加了添加/删除范围的概念,或者允许您推迟更新并手动触发它们。例如看这个 Stack Overflow 问题:

    ObservableCollection Doesn't support AddRange method, so I get notified for each item added, besides what about INotifyCollectionChanging?

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

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

    这些可让您更有效地管理 UI 更新。 ItemsControl 如何处理集合更改事件,该事件详细说明更改的项目列表,这取决于 WPF 框架本身。我假设它可以智能地处理这个问题!

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

    【讨论】:

    • 快速浏览链接问题的实现会发现实现效率低下。基本上,每个添加的项目都会引发 CollectionChanged 事件,然后再次重置集合!
    • @KentBoogaart 嗨肯特,你的意思是这样的答案吗?对我来说看起来不错。 AddRange 方法迭代添加的项目,然后触发单个 CollectionChanged 事件,更改类型为“添加”,提供添加的项目列表。代码的格式虽然不是很好;-)
    • 由于 RangeObservableCollection 扩展了 ObservableCollection,因此对每个项目调用 Add 会导致为每个添加的项目引发 CollectionChangedEvent。然后在添加所有项目后重置集合,所有这些努力都白费了。
    • 除非它没有,因为如果设置了标志,链接的代码还会覆盖 OnCollectionChanged 以抑制 CollectionChangedEvent; AddRange 方法设置此标志,循环并为每个项目调用 Add,然后取消设置标志。
    【解决方案3】:

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

    【讨论】:

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

    微软没有提供它们一定是有原因的

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

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

    是的。当您这样做时,您会发现集合必须选择如何/何时传播这些更改。我从未尝试过,但我认为 View 或 ViewModel 可以做出比可重用集合更好的决策。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多