我想知道ObservableCollection和BindingList之间的区别,因为我已经使用它们来通知源中的任何添加/删除更改,但我实际上不知道什么时候更喜欢其中一个。

为什么我要选择下面的一个而不是另一个呢?

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

or

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

一个ObservableCollection可以像任何集合一样从UI更新。真正的区别很简单:

ObservableCollection<T>实现INotifyCollectionChanged,它在集合发生变化时提供通知(你猜的是^^) 它允许绑定引擎在observableccollection更新时更新UI。

而BindingList<T>实现了IBindingList。

IBindingList提供关于集合更改的通知,但不仅如此。它提供了一大堆的功能,可以被UI使用来提供更多的东西,而不仅仅是UI根据变化更新,比如:

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

所有这些功能在ObservableCollection<T>中都不可用

另一个区别是,当BindingList的项实现INotifyPropertyChanged时,BindingList转发项更改通知。如果一个项目引发了一个PropertyChanged事件,BindingList将接收它并引发一个带有ListChangedType的ListChangedEvent。ItemChanged和OldIndex=NewIndex(如果一个项目被替换,OldIndex=-1)。ObservableCollection不传递项目通知。

注意,在Silverlight中,BindingList是不可用的选项:你可以使用ObservableCollections和ICollectionView(和IPagedCollectionView,如果我没记错的话)。


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

从WPF的角度来看,BindingList并没有得到很好的支持,除非你真的需要,否则你永远不会在WPF项目中使用它。


ObservableCollection和BindingList之间的一个更大的区别是很方便的,并且可以作为主题的投标决策因素:

BindingList列表更改处理器:

ObservableCollection集合变化:

如果一个项目的属性在BindingList中被改变了,ListChanged事件会给你完整的细节 of property(在PropertyDescriptor中)和ObservableCollection不会给你这个。事实上 ObservableCollection不会引发属性的更改事件 在某项中更改。

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


最重要的区别,比如包含元素的特性和更改通知,已经在公认的答案中提到了,但还有更多,也值得一提:

性能

当AddNew被调用时,BindingList<T>通过IndexOf查找来搜索添加的项。如果T实现了INotifyPropertyChanged,更改后的元素的索引也会被IndexOf搜索(尽管只要同一项重复更改,就不会有新的查找)。如果您在集合中存储了数千个元素,那么ObservableCollection<T>(或具有O(1)查找代价的自定义IBindingList实现)可能更可取。

完整性

The IBindingList interface is a huge one (maybe not the cleanest design) and allows the implementors to implement only a subset of its features. For example, the AllowNew, SupportsSorting and SupportsSearching properties tell whether AddNew, ApplySort and Find methods can be used, respectively. It often surprises people that BindingList<T> itself does not support sorting. Actually it provides some virtual methods letting the derived classes add the missing features. The DataView class is an example for a full IBindingList implementation; however, it is not for typed collections in the first place. And the BindingSource class in WinForms is a hybrid example: it supports sorting if it wraps another IBindingList implementation, which supports sorting. ObservableCollection<T> is already a complete implementation of the INotifyCollectionChanged interface (which has only a single event). It also has virtual members but ObservableCollection<T> is typically derived for the same reason as its base Collection<T> class: for customizing add/remove items (eg. in a data model collection) rather than adjusting binding features.

复制vs.换行

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

BindingList<T> acts as an observable wrapper for the provided list, and the changes performed on the BindingList<T> will be reflected on the underlying collection as well. ObservableCollection<T> on the other hand passes a new List<T> instance to the base Collection<T> constructor and copies the elements of the original collection into this new list. Of course, if T is a reference type changes on the elements will be visible from the original collection but the collection itself will not be updated.


两者都有优点和缺点,需要一些时间来发现。

我在使用BindingList时遇到了一些麻烦,因为更改通知事件只发生在删除项之后,并且只提供了一个索引(这意味着如果实现了一些删除后机制,则必须跟踪哪个对象位于哪个位置)。另一方面,ObservableCollection为您提供已删除项的列表。

BindingList有一个方便的AddNew()方法,它允许派生类实现工厂模式,例如,根据父集合的值初始化新项(例如,如果集合包含子项,则父集合的外键)。

还请注意,使用(实体框架中的ToBindingList扩展)从ObservableCollection中获得BindingList非常容易,并且返回(派生的)BindingList实现了一些功能,比如排序,这在普通的BindingList中是缺乏的。