C# INotifyCollectionChanged—它多久启动一次(以及它们如何使其如此高效/快速)?

C# INotifyCollectionChanged—它多久启动一次(以及它们如何使其如此高效/快速)?,c#,wpf,performance,observablecollection,inotifycollectionchanged,C#,Wpf,Performance,Observablecollection,Inotifycollectionchanged,基本上,我想知道它到底是如何有效的 示例代码: void GetItems() { foreach (var item in items) myObservableCollection.Add(item); } 这不会每次都触发CollectionChanged事件,导致UI每次都必须刷新吗?或者它这样做是为了等待GetItems函数完成 基本上,WPF似乎处理得很好,我想知道他们是如何做到的。每次更改都会触发事件 GUI不必每次都做出反应和刷新,它可以推迟这一过程。

基本上,我想知道它到底是如何有效的

示例代码:

void GetItems()
{
    foreach (var item in items)
        myObservableCollection.Add(item);
}
这不会每次都触发CollectionChanged事件,导致UI每次都必须刷新吗?或者它这样做是为了等待GetItems函数完成


基本上,WPF似乎处理得很好,我想知道他们是如何做到的。

每次更改都会触发事件

GUI不必每次都做出反应和刷新,它可以推迟这一过程。
我知道WinForms会对此进行优化,我认为WPF也有类似的方法

提供了有关如何解决数据绑定的一些背景信息,包括不同项源的性能影响。看看这一节

考虑一个场景,其中有一个CLR List对象 要在列表框中显示的员工列表。创建 这两个对象之间的对应关系,将绑定您的员工 列表到列表框的ItemsSource属性。然而,假设你 让一名新员工加入您的团队。你可能会这么想 要将此人插入绑定的列表框值,您需要 只需将此人添加到您的员工列表中,并期望此更改生效 由数据绑定引擎自动识别

这一假设将被证明是错误的;事实上,这一变化不会改变 将自动反映在列表框中。这是因为CLR 列表对象不会自动引发已更改的集合 事件为了让列表框拾取更改,您需要 必须重新创建员工列表并将其重新附加到 ListBox的ItemsSource属性。虽然这个解决方案有效,但它仍然有效 引入了巨大的性能影响。每次重新分配 ItemsSource将ListBox转换为新对象,ListBox首先丢弃 并重新生成其整个列表。演出 如果列表框映射到复杂的数据模板,则影响会放大

解决这个问题的一个非常有效的方法是让你的员工 列出一个可观察到的集合。可观测的收集物体 引发数据绑定引擎可以执行的更改通知 接收事件从ItemsControl中添加或删除项 无需重新生成整个列表

1项的更新时间(毫秒)

  • 到CLR列表对象=1656毫秒
  • 到可观察到的收集=20 ms
WPF从不直接绑定到集合。如果将集合指定为绑定源,WPF实际上会绑定到集合的源

集合视图是绑定源集合顶部的层 这使您可以基于导航和显示源集合 排序、筛选和分组查询,而无需更改 底层源集合本身。集合视图还维护 指向集合中当前项的指针。如果来源 集合实现INotifyCollectionChanged接口 CollectionChanged事件引发的更改将传播到 观点


如果您想查看UI请求新结果的频率,请将其作为公共属性公开,并在myObservableCollection的公共属性的get(assessor)中放置调试行。

因此,运行和更新GUI的代码基本上是在进行性能优化。是的。WinForms只是在您更改属性时使控件无效,并且仅在事件队列为空时重新绘制控件。在WPF中,每个
CollectionChanged
事件将一个帧推送到主线程的
调度程序
队列上;当dispatcher找到它时,它将
从源值调用一个绑定更新。因此,如果有很多更改通知需要处理,用户就不会注意到任何减速或无响应;这仅仅意味着一个特定的控件可能会显示过时的数据一小段时间,直到轮到它被处理为止。