ObservableCollection和BindingList之间的区别


236

我想知道和之间的区别ObservableCollectionBindingList因为我都曾用两者来通知Source中的任何添加/删除更改,但实际上我不知道何时比另一个更喜欢一个。

为什么我要选择以下一项?

ObservableCollection<Employee> lstEmp = new ObservableCollection<Employee>();

要么

BindingList<Employee> lstEmp = new BindingList<Employee>();

Answers:


278

一个ObservableCollection可以从用户界面酷似任何集合进行更新。真正的区别非常简单:

ObservableCollection<T>实现INotifyCollectionChanged在集合更改时提供通知的实现(您猜对了^^),它允许绑定引擎在更新时更新UI ObservableCollection

但是,BindingList<T>工具IBindingList

IBindingList提供有关集合更改的通知,但不仅限于此。它提供了一整套功能,UI可以使用这些功能提供很多功能,而不仅仅是根据更改进行UI更新,例如:

  • 排序
  • 正在搜寻
  • 通过工厂添加(AddNew成员函数)。
  • 只读列表(CanEdit属性)

所有这些功能在 ObservableCollection<T>

另一个不同之处是,BindingList在实现项目更改时,中继项目更改通知INotifyPropertyChanged。如果某个项目引发了一个PropertyChanged事件,则BindingList它将收到一个ListChangedEvent带有ListChangedType.ItemChanged和的引发a OldIndex=NewIndex(如果已替换了一个项目OldIndex=-1)。ObservableCollection不中继项目通知。

请注意,在Silverlight中,BindingList不是可选选项:但是,您可以使用ObservableCollections和ICollectionView(并且IPagedCollectionView我记得很好)。


5
要考虑的另一件事是性能,请参阅:themissingdocs.net/wordpress/?p=465
Jarek Mazur

谢谢,我不知道BindingList的实际实现。我倾向于使用ObservableCollection和ICollectionView
Eilistraee,2015年

5
尽管此答案中的信息正确无误,但任何WPF用户都应当心:BindingList不实现INotifyCollectionChanged,并且如果绑定到控件的ItemsSource属性,则将导致内存泄漏。ObservableCollection确实实现了该接口,不会引起任何此类泄漏。
布兰登胡德

1
如果BindingList实现排序,那么为什么不能对绑定到BindingList的网格进行排序?
罗伯特·哈维

BindingList过时了吗?
Shimmy Weitzhandler,

27

实际的区别在于BindingList用于WinForms,而ObservableCollection用于WPF。

从WPF角度来看,不正确地支持BindingList,除非您确实需要,否则您永远不会在WPF项目中真正使用它。


1
有趣。作为Silverlight开发人员,我不知道这一点。谢谢。而且,如果您想排序和过滤,则ICollectionView实现是您的朋友^^
Eilistraee 2010年

27
为什么它是“不支持”?ViewManager(内部)在PresentationFramework程序集内并对其提供支持。例如,将其绑定到ItemsControl并遵守更改通知(即,添加和删除项)。如果它是WinForms专用的,是否应该更好地将其放在Forms命名空间中?
大卫·基夫

7
与David同意,它在System.Collections命名空间中,因此WPF应该完全支持它。WPF只是UI布局的另一种方式。
贾斯汀

13
同样也同意David的观点,我在WPF中经常使用BindingList,因为ObservableCollection不会从其项中冒充属性更改通知。
失忆症

3
举一个“不支持”的示例:我刚刚在WPF应用程序中发现了内存泄漏,这是由某些未实现INotifyCollectionChanged的BindingLists引起的
Breeze

4

公认的答案已经提到了最重要的区别,例如功能和有关所包含元素的更改通知,但还有更多区别,还值得一提:

性能

AddNew被调用时,BindingList<T>通过对添加的项目搜索IndexOf查找。并且如果T实现INotifyPropertyChanged,还可以搜索已更改元素的索引IndexOf(尽管只要同一项目重复更改,就不会有新的查找)。如果在集合中存储了数千个元素,则ObservableCollection<T>(或IBindingList使用O(1)查找成本的自定义实现)可能会更可取。

完整性

  • IBindingList接口是一个巨大的接口(可能不是最干净的设计),并且允许实现者仅实现其功能的一部分。例如,AllowNewSupportsSortingSupportsSearching属性告诉是否AddNewApplySortFind方法可以分别使用,。人们常常会惊讶于它BindingList<T>本身不支持排序。实际上,它提供了一些虚拟方法,让派生类添加缺少的功能。该DataView班是一个完整的例子IBindingList实施; 但是,它并非首先用于类型化的集合。BindingSourceWinForms中的类是一个混合示例:如果包装另一个IBindingList支持排序的实现,则它支持排序。

  • ObservableCollection<T>已经是INotifyCollectionChanged接口的完整实现(只有一个事件)。它也具有虚拟成员,但ObservableCollection<T>通常出于与其基Collection<T>类相同的原因而派生:用于自定义添加/删除项(例如,在数据模型集合中)而不是调整绑定功能。

复制与包装

双方ObservableCollection<T>BindingList<T>有一个构造函数,它接受一个已经存在的列表。尽管它们在被另一个集合实例化时的行为有所不同:

  • BindingList<T>充当所提供列表的可观察包装器,并且在上执行的更改BindingList<T>也将反映在基础集合上。
  • ObservableCollection<T>另一方面,将新List<T>实例传递给基本Collection<T>构造函数,并将原始集合的元素复制到此新列表中。当然,如果T是引用类型,则对元素的更改将从原始集合中可见,但集合本身不会被更新。

1

多一个很大的区别之间ObservableCollection,并BindingList自带方便,并且可以在该主题的投标决策的因素:

BindingList 列表更改处理程序:

绑定列表列表更改

ObservableCollection 集合变更:

ObervableCollection集合已更改

上面的内容简介:如果某项的属性在中更改BindingList,则该ListChanged事件将为您提供该属性的完整详细信息(在PropertyDescriptor中),ObservableCollection而不会提供给您。实际上, ObservableCollection不会为项目中更改的属性引发更改事件。

以上结论是关于INotifyPropertyChanged模型类中实现的。默认情况下,如果项目中的属性发生更改,则none不会引发更改事件。


我认为此(PropertyDescriptor)可能是内存泄漏的根源
Abdulkarim Kanaan '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.