Czy mam powiązać z ICollectionView lub ObservableCollection

83

Jeśli należy połączyć DataGridsię z

ICollectionView = CollectionViewSource.GetDefaultView(collection)

lub do

ObservableCollection<T> collection; ???

Jaka jest najlepsza praktyka dla MVVM i dlaczego?

Cartesius00
źródło

Odpowiedzi:

129

Ty zawsze wiążą się z ICollectionView, czy zrobić to jawne czy nie.

Załóżmy, że mamy

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

W tym przypadku powiązanie z collectionlub do collectionViewjest jednym i tym samym: silnik powiązań będzie wiązał się z domyślnym widokiem kolekcji (który jest równy referencji collectionView), jeśli powiesz mu, aby się z nim wiązał collection.

Oznacza to, że odpowiedź na Twoje pytanie brzmi: „to absolutnie nie ma znaczenia”.

Dla jasności: nawet jeśli utworzysz powiązanie bezpośrednio z kolekcją, silnik powiązań połączy się z widokiem domyślnym. Modyfikowanie właściwości widoku, takich jak kryteria sortowania, wpłynie na powiązanie, które wydaje się wiązać bezpośrednio z kolekcją, ponieważ za okładkami jest to powiązanie z widokiem domyślnym.

Jest jednak inne interesujące i powiązane pytanie: czy należy wiązać się z domyślnym widokiem kolekcji (tj. Z samą kolekcją, ponieważ nie ma powodu, aby jawnie wiązać się z widokiem domyślnym), czy z innym widokiem tej samej kolekcji?

Biorąc pod uwagę, że każdy widok ma własne pojęcie o bieżącym elemencie, kryteriach sortowania itp., Wynika z tego, że jeśli zamierzasz mieć wiele powiązań z tą samą kolekcją, a powiązane kontrolki muszą mieć odrębne pojęcia dotyczące bieżącego elementu, filtrów i firmy, to chcesz jawnie powiązać wiele widoków tej samej podstawowej kolekcji.

Jon
źródło
1
Świetna odpowiedź. Osobiście wolę powiązać się z kolekcją ObservableCollection teraz, gdy jest ona częścią System.Collections i „czuję się” bardziej reprezentatywną dla czegoś, co reprezentuję w Modelu w przeciwieństwie do Widoku, ale MVVM jest czasami drażliwy w ten sposób.
Berryl
Pozdrawiam odpowiedź. Chciałbym tylko zauważyć, że w Silverlight domyślny CollectionView nie zostanie utworzony dla powiązanych kolekcji, chyba że ta powiązana kolekcja implementuje ICollectionViewFactory.
jspaey
Czy to również / nadal ma zastosowanie do aplikacji uniwersalnych?
Robert MacLean
@RobertMacLean: Nie mam żadnego doświadczenia w programowaniu WP, więc niestety nie mam pojęcia.
Jon
Aby utworzyć jawny widok dla bazowej kolekcji w XAML, Utwórz element CollectionViewSource w Resources. Posiadanie powiązania właściwości CollectionViewSource.Source z kolekcją źródłową. Następnie powiąż właściwość ItemsControl.ItemSource z CollectionViewSource utworzoną w zasobie za pośrednictwem StaticResource. W ten sposób operacja sortowania / filtrowania / grupowania zastosowana do jednego widoku nie „zanieczyszcza” innych elementów ItemsControls, które są powiązane z domyślnym CollectionView.
Frank Liu
35

ObservableCollection<T>implementuje INotifyCollectionChangedi powiadomi interfejs użytkownika, gdy elementy w kolekcji zostaną zmienione.

ICollectionViewdaje możliwość filtrowania, sortowania lub grupowania kolekcji oprócz propagowania INotifyCollectionChangedzdarzeń, jeśli bazowa kolekcja ją implementuje.

Każdy typ działa dobrze z MVVM, o ile się z nim powiążesz. Użyj, ICollectionViewgdy potrzebujesz sortowania, filtrowania lub grupowania. Używaj ObservableCollection<T>bezpośrednio, gdy nie masz.

Jimmie R. Houts
źródło
Ten inny post wydaje się zaprzeczać temu, że ICollectionView zostanie automatycznie zaktualizowany na podstawie zdarzenia zmiany kolekcji ... czy to nieprawda? stackoverflow.com/a/17906474/3195477
UuDdLrLrSs
@UuDdLrLrSs, jeśli elementy w kolekcji zostaną zmodyfikowane, interfejs użytkownika powiązany z tymi elementami lub właściwościami tych elementów zostanie zaktualizowany bez konieczności wywoływania Refresh w kolekcji. Drugi post zawiera w szczególności pytanie o zmianę właściwości elementów w kolekcji i automatyczne wyzwalanie odświeżania ICollectionView, aby upewnić się, że zawiera tylko elementy, które nadal spełniają kryteria filtru. Na podstawie odpowiedzi w innym poście należałoby wywołać metodę Refresh (), aby zaktualizować „listę” elementów w kolekcji.
Jimmie R. Houts
9

Wystarczy dodać do tego, co powiedział Jon. Główną różnicą jest to, że używając CollectionViewSource.GetDefaultView(collection), uzależniasz ViewModel od WPF. Wielu purystów MVVM nie lubi tego, a to pozostawiłoby ObservableCollection tylko prawidłową opcję.

Inną opcją byłoby użycie ICollectionViewi użycie klasy, która ją implementuje, ale nie jest częścią samego WPF.

Euforyk
źródło
1
To jednak nie jest główna różnica. Zwróć uwagę na tag wpf. „[jeśli] powiązane kontrolki muszą mieć odrębne pojęcia dotyczące bieżącego elementu, filtrów i firmy, to co chcesz, to jawnie powiązać z wieloma widokami tej samej podstawowej kolekcji”. To jest różnica. Bycie „purystą”, cokolwiek to jest, oznacza, że ​​nie można filtrować itp. Zobacz odpowiedź Jimmiego Houts, która skupia się na rzeczywistej różnicy w jaśniejszym języku.
Dirk Bester,
7

Nie sądzę, żeby to miało coś wspólnego ze MVVMsobą. ICollectionViewzapewnia dodatkowe funkcje, takie jak grupowanie sortowania itp., Jeśli potrzebujesz, IColectionViewpo prostu użyjObservableCollection

Haris Hasan
źródło
2

Powiążesz się z widokiem, jeśli chcesz, aby Twoja siatka wyświetlała ustawienia zastosowane do widoku, np. Filtrowanie, w przeciwnym razie widok jest zbędny.

devdigital
źródło