Разница между ObservableCollection и BindingList

236

Я хочу знать разницу между ObservableCollectionи BindingListпотому что я использовал оба, чтобы уведомлять о любых изменениях добавления / удаления в Source, но на самом деле я не знаю, когда предпочесть одно другому.

Почему я бы выбрал одно из следующего над другим?

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

или

BindingList<Employee> lstEmp = new BindingList<Employee>();
Азхар
источник

Ответы:

278

An ObservableCollectionможет быть обновлен из интерфейса точно так же, как любая коллекция. Истинная разница довольно проста:

ObservableCollection<T>Реализует, INotifyCollectionChangedкоторый предоставляет уведомление при изменении коллекции (как вы уже догадались ^^). Он позволяет механизму привязки обновлять пользовательский интерфейс при ObservableCollectionобновлении.

Однако BindingList<T>реализует IBindingList.

IBindingListобеспечивает уведомление об изменениях коллекции, но не только. Он предоставляет целый набор функциональных возможностей, которые пользовательский интерфейс может использовать для предоставления гораздо большего, чем только обновления пользовательского интерфейса в соответствии с изменениями, например:

  • Сортировка
  • Поиск
  • Добавить через фабрику (функция-член AddNew).
  • Список только для чтения (свойство CanEdit)

Все эти функции недоступны в ObservableCollection<T>

Другое отличие состоит в том, что BindingListретранслирует уведомления об изменении элемента, когда его элементы реализуются INotifyPropertyChanged. Если предмет вызывает PropertyChangedсобытие, BindingListполучатель получает рейз ListChangedEventс ListChangedType.ItemChangedи OldIndex=NewIndex(если предмет был заменен, OldIndex=-1). ObservableCollectionне передает уведомления о предметах.

Обратите внимание, что в Silverlight BindingListэта опция недоступна: однако вы можете использовать ObservableCollections и ICollectionView(и, IPagedCollectionViewесли я хорошо помню).

Илистри
источник
5
Еще одна вещь, которую следует учитывать, это производительность, см .: themissingdocs.net/wordpress/?p=465
Ярек Мазур
Спасибо, я не знал о фактической реализации BindingList. Я предпочитаю использовать ObservableCollection и ICollectionView
Илистри
5
Хотя информация в этом ответе верна, все пользователи WPF должны остерегаться: BindingList не реализует INotifyCollectionChanged и приведет к утечке памяти, если она связана со свойством ItemsSource элемента управления. ObservableCollection реализует интерфейс и не вызовет таких утечек.
Брэндон Худ
1
Если BindingList реализует сортировку, то почему вы не можете отсортировать сетку, привязанную к BindingList?
Роберт Харви
Устарел BindingList?
Шимми Вейцхандлер
27

Практическое отличие состоит в том, что BindingList предназначен для WinForms, а ObservableCollection - для WPF.

С точки зрения WPF, BindingList не поддерживается должным образом, и вы бы никогда не использовали его в проекте WPF без необходимости.

Дин Мел
источник
1
Интересный. Как разработчик Silverlight, я этого не знал. Спасибо. И если вы хотите сортировать и фильтровать, реализации ICollectionView - ваш друг ^^
Eilistraee
27
Почему это "Не поддерживается"? ViewManager (внутренний) находится в сборке PresentationFramework и поддерживает ее. Например, привяжите его к ItemsControl, и уведомления об изменениях будут учтены (то есть элементы будут добавлены и удалены). Если бы это было специфично для WinForms, не лучше ли поместить его в пространство имен Forms?
Дэвид Кифф
7
Согласен с Дэвидом, он находится в пространстве имен System.Collections, поэтому он должен полностью поддерживаться WPF. WPF - это просто другой способ макета пользовательского интерфейса.
Джастин
13
Согласитесь также с Дэвидом, я часто использую BindingList в WPF, потому что ObservableCollection не будет пузырить уведомления об изменениях свойств из своих элементов.
амнезия
3
Чтобы привести пример для «не поддерживающих»: я только что обнаружил утечку памяти в своем приложении WPF, вызванную тем, что некоторые BindingLists не реализуют INotifyCollectionChanged
Breeze
4

Наиболее важные различия, такие как функции и уведомления об изменениях в содержащихся элементах, уже упомянуты в принятом ответе, но есть и другие, о которых также стоит упомянуть:

Производительность

Когда AddNewвызывается, BindingList<T>ищет добавленный элемент путем IndexOfпоиска. И если Tреализует INotifyPropertyChangedиндекс измененного элемента, также выполняется поиск IndexOf(хотя нет нового поиска, пока один и тот же элемент изменяется неоднократно). Если вы храните тысячи элементов в коллекции, то ObservableCollection<T>(или пользовательская IBindingListреализация с O (1) стоимостью поиска) может быть более предпочтительной.

завершенность

  • IBindingListИнтерфейс огромный один (возможно , не самый чистый дизайн) и позволяет разработчикам реализовать только часть его функций. Так , например, AllowNew, SupportsSortingи SupportsSearchingсвойства сказать , является ли AddNew, ApplySortи Findмогут быть использованы методы, соответственно. Людей часто удивляет, что BindingList<T>сама не поддерживает сортировку. На самом деле он предоставляет некоторые виртуальные методы, позволяющие производным классам добавлять недостающие функции. DataViewКласс является примером для полного IBindingListосуществления; однако, это не для типизированных коллекций во-первых. И BindingSourceкласс в WinForms является гибридным примером: он поддерживает сортировку, если оборачивает другую 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 Обработчик изменения списка:

Изменение списка BindingList

ObservableCollection Изменение коллекции:

Коллекция ObervableCollection изменена

Краткое изложение: Если свойство элемента изменяется BindingList, ListChangedсобытие предоставит вам полную информацию о свойстве (в PropertyDescriptor) и ObservableCollectionне даст вам этого. Фактически ObservableCollectionне вызовет событие change для свойства, измененного в элементе.

Выше заключение в отношении INotifyPropertyChangedреализованных в модельных классах. По умолчанию никто не вызывает измененное событие, если свойство изменено в элементе.

Кило Рен
источник
Я думаю, что это (PropertyDescriptor) может быть источником утечки памяти
Абдулкарим Канаан