Должен ли я привязаться к ICollectionView или ObservableCollection


83

Если привязаться DataGridк

ICollectionView = CollectionViewSource.GetDefaultView(collection)

или в

ObservableCollection<T> collection; ???

Какая лучшая практика для MVVM и почему?

Ответы:


129

Вы всегда привязываетесь к объекту ICollectionView, вне зависимости от того, явно вы это делаете или нет.

Предположим, что мы имеем

var collection = new ObservableCollection<string>();
var collectionView = CollectionViewSource.GetDefaultView(collection);

В этом случае привязка к collectionили к collectionViewявляется одним и тем же: механизм привязки будет привязан к представлению коллекции по умолчанию (которое равно ссылке collectionView), если вы укажете ему привязку к collection.

Это означает, что ответ на ваш вопрос - «это абсолютно безразлично».

Чтобы быть полностью ясным: даже если вы привязываетесь к коллекции напрямую, механизм привязки будет привязан к представлению по умолчанию. Изменение свойств представления, таких как критерии сортировки, повлияет на привязку, которая, как представляется, связана непосредственно с коллекцией, так как вместо этого она является привязкой к представлению по умолчанию.

Однако есть еще один интересный и связанный с этим вопрос: следует ли привязываться к представлению коллекции по умолчанию (т. Е. К самой коллекции, потому что нет причин явно привязываться к представлению по умолчанию) или к другому представлению той же коллекции?

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


1
Отличный ответ. Я предпочитаю привязаться к ObservableCollection теперь, когда он является частью System.Collections и «ощущается» более репрезентативным для того, что я представляю в модели, а не в представлении, но MVVM иногда в этом случае немного раздражает.
Berryl

Отличный ответ. Я просто хотел бы отметить, что в Silverlight CollectionView по умолчанию не будет создаваться для связанных коллекций, если эта связанная коллекция не реализует ICollectionViewFactory.
jspaey

Применимо ли это также / по-прежнему к универсальным приложениям?
Роберт Маклин,

@RobertMacLean: У меня нет опыта разработки WP, поэтому, к сожалению, не знаю.
Джон

Чтобы создать явное представление для базовой коллекции в xaml, создайте элемент CollectionViewSource в файле Resources. Связь свойства CollectionViewSource.Source с базовой коллекцией. Затем привяжите свое свойство ItemsControl.ItemSource к CollectionViewSource, которое вы создали в ресурсе через StaticResource. Таким образом, операция сортировки / фильтрации / группировки, примененная к одному представлению, не будет «загрязнять» другие элементы ItemsControl, которые привязаны к Default CollectionView.
Фрэнк Лю

35

ObservableCollection<T>реализует INotifyCollectionChangedи будет уведомлять пользовательский интерфейс, когда элементы в коллекции были изменены.

ICollectionViewдаст вам возможность фильтровать, сортировать или группировать коллекцию в дополнение к распространению INotifyCollectionChangedсобытий, если базовая коллекция реализует это.

Любой тип хорошо работает с MVVM, если вы к нему привязаны. Используйте, ICollectionViewкогда вам нужна сортировка, фильтрация или группировка. Используйте ObservableCollection<T>напрямую, когда вы этого не делаете.


Этот другой пост, похоже, противоречит тому, что ICollectionView будет автоматически обновляться на основе события изменения коллекции ... это неверно? stackoverflow.com/a/17906474/3195477
UuDdLrLrSs

@UuDdLrLrSs, если элементы в коллекции изменены, пользовательский интерфейс, связанный с этими элементами, или свойства этих элементов будут обновляться без необходимости вызывать Refresh для коллекции. Другой пост специально спрашивает об изменении свойств элементов в коллекции и об автоматическом запуске обновления ICollectionView, чтобы убедиться, что он включает только элементы, которые все еще соответствуют критериям фильтра. Основываясь на ответе в другом посте, вам нужно будет вызвать метод Refresh (), чтобы обновить «список» элементов в коллекции.
Джимми Р. Хаутс

9

Просто чтобы добавить к тому, что сказал Джон. Основное отличие состоит в том, что, используя CollectionViewSource.GetDefaultView(collection), вы делаете ViewModel зависимым от WPF. Многим пуристам MVVM это не нравится, и это оставит только допустимый вариант ObservableCollection.

Другой вариант - ICollectionViewиспользовать класс, реализующий его, но не являющийся частью самого WPF.


1
Но это не главное отличие. Обратите внимание на тег wpf. «[если] привязанные элементы управления должны иметь различные представления о текущем элементе, фильтрах и компании, тогда вы хотите явно привязать к нескольким представлениям одной и той же базовой коллекции». Вот в чем разница. Быть «пуристом», что бы это ни было, означает, что вы не можете фильтровать и т. Д. См. Ответ Джимми Хаутса, в котором основное внимание уделяется действительной разнице в более ясном языке.
Дирк Бестер

7

Я не думаю, что это имеет какое-то отношение к MVVMсамому себе. ICollectionViewпредоставляет дополнительные функции, такие как сортировка группировки и т. д., если они вам нужны, в IColectionViewпротивном случае просто используйтеObservableCollection


2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.