ObservableCollection和BindingList的区别

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

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

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

BindingList<Employee> lstEmp = new BindingList<Employee>();
72836 次浏览

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

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

然而,BindingList<T>实现了IBindingList

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

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

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

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

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

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

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

ObservableCollectionBindingList之间有一个更方便的很大的区别,可以作为主题的投标决定因素:

BindingList列表更改处理程序:

BindingList List Change

ObservableCollection集合更改:

ObervableCollection Collection Changed

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

.在一个项目中更改

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

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

性能

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

完整性

  • IBindingList接口是一个巨大的接口(可能不是最干净的设计),并且只允许实现者实现其功能的一个子集。例如,AllowNewSupportsSortingSupportsSearching属性分别表示是否可以使用AddNewApplySortFind方法。BindingList<T>本身不支持排序,这常常让人感到惊讶。实际上,它提供了一些虚拟方法,让派生类添加缺少的特性。DataView类是一个完整的IBindingList实现的例子;但是,它一开始就不适合类型化集合。WinForms中的AllowNew0类是一个混合的例子:如果它包装了另一个支持排序的IBindingList实现,它就支持排序。

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

复制vs.换行

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

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

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

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

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

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