Soll ich mich an ICollectionView oder ObservableCollection binden?

83

Sollte man sich DataGridan die binden

ICollectionView = CollectionViewSource.GetDefaultView(collection)

oder zum

ObservableCollection<T> collection; ???

Was ist die beste Vorgehensweise für MVVM und warum?

Cartesius00
quelle

Antworten:

128

Sie binden immer an ein ICollectionView, ob Sie es explizit machen oder nicht.

Angenommen, wir haben

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

In diesem Fall ist die Bindung an collectionoder an collectionViewein und dieselbe: Die Bindungs-Engine bindet an die Standardauflistungsansicht (deren Referenz gleich ist collectionView), wenn Sie sie anweisen, an zu binden collection.

Dies bedeutet, dass die Antwort auf Ihre Frage lautet "es macht absolut keinen Unterschied".

Um ganz klar zu sein: Selbst wenn Sie direkt an die Sammlung binden, wird die Bindungs-Engine an die Standardansicht gebunden. Das Ändern von Eigenschaften der Ansicht, z. B. Sortierkriterien, wirkt sich auf die Bindung aus, die anscheinend direkt an die Sammlung gebunden ist, da hinter den Deckblättern stattdessen eine Bindung an die Standardansicht erfolgt.

Es gibt jedoch noch eine andere interessante und verwandte Frage: Sollte man sich an die Standardauflistungsansicht (dh an die Auflistung selbst, da es keinen Grund gibt, explizit an die Standardansicht zu binden) oder an eine andere Ansicht derselben Auflistung binden?

In Anbetracht der Tatsache, dass jede Ansicht ihre eigene Vorstellung von aktuellem Element, Sortierkriterien usw. hat, folgt daraus, dass, wenn Sie mehrere Bindungen an dieselbe Sammlung haben möchten und die gebundenen Steuerelemente unterschiedliche Vorstellungen von aktuellem Element, Filtern und Unternehmen haben müssen Sie möchten explizit an mehrere Ansichten derselben zugrunde liegenden Sammlung binden.

Jon
quelle
1
Tolle Antwort. Meine eigene Präferenz ist es, mich jetzt an die ObservableCollection zu binden, da sie Teil von System.Collections ist und sich repräsentativer für etwas "anfühlt", das ich über das Modell im Gegensatz zur Ansicht darstelle, aber MVVM ist manchmal auf diese Weise empfindlich.
Berryl
Antwort erstellen. Ich möchte nur darauf hinweisen, dass in Silverlight keine Standard-CollectionView für gebundene Sammlungen erstellt wird, es sei denn, diese gebundene Sammlung implementiert ICollectionViewFactory.
Jspaey
Gilt dies auch / noch für Universal Apps?
Robert MacLean
@ RobertMacLean: Ich habe keine WP-Entwicklungserfahrung, also leider keine Ahnung.
Jon
Um eine explizite Ansicht für eine zugrunde liegende Sammlung in xaml zu erstellen, erstellen Sie ein CollectionViewSource-Element in den Ressourcen. Die CollectionViewSource.Source-Eigenschaft ist mit der zugrunde liegenden Sammlung verbunden. Binden Sie dann Ihre ItemsControl.ItemSource-Eigenschaft an die CollectionViewSource, die Sie über StaticResource in der Ressource erstellt haben. Auf diese Weise "kontaminieren" Sortier- / Filter- / Gruppierungsvorgänge, die auf eine Ansicht angewendet werden, nicht andere ItemsControls, die an die Standard-Sammlungsansicht gebunden sind.
Frank Liu
35

ObservableCollection<T>implementiert INotifyCollectionChangedund benachrichtigt die Benutzeroberfläche, wenn die Elemente in der Sammlung geändert wurden.

ICollectionViewbietet Ihnen die Möglichkeit, die Sammlung zu filtern, zu sortieren oder zu gruppieren und INotifyCollectionChangedEreignisse zu propagieren , wenn die zugrunde liegende Sammlung sie implementiert.

Beide Typen funktionieren gut mit MVVM, solange Sie daran binden. Verwenden ICollectionViewSie diese Option, wenn Sie sortieren, filtern oder gruppieren müssen. Verwenden Sie ObservableCollection<T>direkt, wenn Sie nicht.

Jimmie R. Houts
quelle
Dieser andere Beitrag scheint zu widersprechen, dass ICollectionView aufgrund eines Ereignisses mit geänderter Sammlung automatisch aktualisiert wird ... ist es falsch? stackoverflow.com/a/17906474/3195477
UuDdLrLrSs
@UuDdLrLrSs Wenn die Elemente in der Sammlung geändert werden, wird die Benutzeroberfläche, die an diese Elemente gebunden ist, oder die Eigenschaften dieser Elemente aktualisiert, ohne dass Refresh für die Sammlung aufgerufen werden muss. Der andere Beitrag fragt speziell nach dem Ändern der Eigenschaften von Elementen in der Sammlung und dem automatischen Auslösen einer Aktualisierung der ICollectionView, um sicherzustellen, dass nur Elemente enthalten sind, die noch den Filterkriterien entsprechen. Basierend auf der Antwort im anderen Beitrag müssten Sie die Refresh () -Methode aufrufen, um die "Liste" der Elemente in der Sammlung zu aktualisieren.
Jimmie R. Houts
9

Nur um zu dem hinzuzufügen, was Jon gesagt hat. Der Hauptunterschied besteht darin, dass CollectionViewSource.GetDefaultView(collection)Sie mit ViewModel von WPF abhängig machen. Viele MVVM-Puristen mögen dies nicht und dies würde ObservableCollection nur als gültige Option belassen.

Eine andere Möglichkeit wäre, ICollectionVieweine Klasse zu verwenden, die sie implementiert, aber nicht Teil von WPF selbst ist.

Euphorisch
quelle
1
Das ist jedoch nicht der Hauptunterschied. Beachten Sie das wpf-Tag. "[Wenn] die gebundenen Steuerelemente unterschiedliche Vorstellungen von aktuellem Element, Filtern und Unternehmen haben müssen, möchten Sie explizit an mehrere Ansichten derselben zugrunde liegenden Sammlung binden." Das ist der Unterschied. Ein "Purist" zu sein, was auch immer das ist, bedeutet, dass Sie nicht filtern können usw. Siehe die Antwort von Jimmie Houts, die sich auf den tatsächlichen Unterschied in einer klareren Sprache konzentriert.
Dirk Bester
7

Ich denke nicht, dass es irgendetwas mit sich MVVMselbst zu tun hat. ICollectionViewbietet zusätzliche Funktionen wie Soring Grouping usw., falls Sie diese benötigen, verwenden Sie sie IColectionVieweinfachObservableCollection

Haris Hasan
quelle
2

Sie würden an die Ansicht binden, wenn Ihr Raster die auf die Ansicht angewendeten Einstellungen anzeigen soll, z. B. Filtern, andernfalls ist die Ansicht redundant.

devdigital
quelle