Bei der Implementierung des ViewModel in einer WPF-Anwendung mit Model-View-ViewModel-Architektur scheint es zwei Hauptoptionen zu geben, wie es datenbindbar gemacht werden kann. Ich habe Implementierungen gesehen, die DependencyProperty
für Eigenschaften verwendet werden, an die die Ansicht gebunden werden soll, und ich habe INotifyPropertyChanged
stattdessen die Implementierung des ViewModel gesehen .
Meine Frage ist, wann ich eines dem anderen vorziehen soll? Gibt es Leistungsunterschiede? Ist es wirklich eine gute Idee, WPF die ViewModel-Abhängigkeiten zu geben? Was muss ich bei der Entwurfsentscheidung noch beachten?
INotifyPropertyChanged
.Antworten:
Kent hat einen interessanten Blog zu diesem Thema geschrieben: Modelle anzeigen: POCOs versus DependencyObjects .
Kurze Zusammenfassung:
Ich bevorzuge den POCO-Ansatz. Eine Basisklasse für PresentationModel (auch bekannt als ViewModel), die die INotifyPropertyChanged-Schnittstelle implementiert, finden Sie hier: http://compositeextensions.codeplex.com
quelle
Laut dem WPF-Leistungsleitfaden weisen DependencyObjects definitiv eine bessere Leistung auf als POCOs, die INotifyPropertyChanged implementieren:
http://msdn.microsoft.com/en-us/library/bb613546.aspx
quelle
Die Auswahl basiert vollständig auf Ihrer Geschäftslogik und der Abstraktionsstufe der Benutzeroberfläche. Wenn Sie keine gute Trennung wünschen, funktioniert DP für Sie.
DependencyProperties wird hauptsächlich auf VisualElements-Ebene angewendet. Daher ist es keine gute Idee, wenn wir für jede unserer Geschäftsanforderungen viele DPs erstellen. Außerdem fallen für DP höhere Kosten an als für INotifyPropertyChanged. Wenn Sie ein WPF / Silverlight entwerfen, versuchen Sie, Benutzeroberfläche und ViewModel vollständig getrennt zu gestalten, damit wir jederzeit die Steuerelemente für Layout und Benutzeroberfläche ändern können (basierend auf Thema und Stilen).
Lesen Sie auch diesen Beitrag - /programming/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . Der Link enthält viele Verweise auf das Model-View-ViewModel-Muster, das für diese Diskussion sehr relevant ist.
quelle
Vom Standpunkt der Ausdruckskraft aus genieße ich es sehr, Abhängigkeitseigenschaften zu verwenden und bei dem Gedanken daran zusammenzucken
INotifyPropertyChanged
. Abgesehen von denstring
Eigenschaftsnamen und möglichen Speicherverlusten aufgrund von EreignisabonnementsINotifyPropertyChanged
ist dies ein viel expliziterer Mechanismus.Abhängigkeitseigenschaften implizieren "wenn dies der Fall ist" unter Verwendung leicht verständlicher statischer Metadaten. Es ist ein deklarativer Ansatz, der meine Stimme für Eleganz erhält.
quelle
[CallerMemberName]
.INotifyPropertyChanged
Bei Verwendung haben Sie auch die Möglichkeit, dem Code Ihrer Getter und dem Setter Ihrer Eigenschaften mehr Logik hinzuzufügen.DependencyProperty
Beispiel:In Ihrem Getter und Setter - alles, was Sie tun können, ist einfach SetValue bzw. GetValue aufzurufen. In anderen Teilen des Frameworks wird der Getter / Setter nicht aufgerufen, sondern er ruft direkt SetValue, GetValue auf, sodass Ihre Eigenschaftslogik dies nicht tun würde zuverlässig ausgeführt werden.
Mit
INotifyPropertyChanged
definiert ein Ereignis:Und dann haben Sie einfach irgendwo in Ihrem Code eine Logik und rufen dann auf:
Dies kann in einem Getter / Setter oder irgendwo anders sein.
quelle
Abhängigkeitseigenschaften sollen die Bindung (als Ziel) an UI-Elemente unterstützen, nicht als Quelle für die Datenbindung. Hier kommt INotifyProperty ins Spiel. Aus reiner Sicht sollten Sie DP nicht in ViewModels verwenden.
"Um die Quelle einer Bindung zu sein, muss eine Eigenschaft keine Abhängigkeitseigenschaft sein. Sie können jede CLR-Eigenschaft als Bindungsquelle verwenden. Um jedoch das Ziel einer Bindung zu sein, muss die Eigenschaft a sein Abhängigkeitseigenschaft: Damit eine Einweg- oder Zweiwegbindung wirksam ist, muss die Quelleigenschaft Änderungsbenachrichtigungen unterstützen, die an das Bindungssystem und damit an das Ziel weitergegeben werden. Für benutzerdefinierte CLR-Bindungsquellen bedeutet dies, dass die Eigenschaft INotifyPropertyChanged unterstützen muss. Sammlungen sollten INotifyCollectionChanged unterstützen. "
Alle Abhängigkeitsobjekte können nicht serialisiert werden (dies kann die Verwendung von ViewModels und DTOs (POCOs) behindern.
Es gibt Unterschiede zwischen DP in Silverlight und WPF.
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
quelle
Auch ich musste diese Entscheidung kürzlich in Betracht ziehen.
Ich stellte fest, dass der INotifyPropertyChanged-Mechanismus meinen Anforderungen besser entsprach, da ich meine GUI auf ein vorhandenes Geschäftslogik-Framework kleben konnte, ohne den Status zu duplizieren. Das von mir verwendete Framework hatte ein eigenes Beobachtermuster und es war einfach, eine Benachrichtigungsebene an die nächste weiterzuleiten. Ich hatte einfach eine Klasse, die die Beobachterschnittstelle aus meinem Geschäftslogik-Framework und der INotifyPropertyChanged-Schnittstelle implementierte.
Mit DP können Sie das Backend, in dem der Status gespeichert ist, nicht selbst definieren. Ich hätte .net eine Kopie jedes Statuselements zwischenspeichern lassen müssen, an das ich gebunden war. Dies schien ein unnötiger Aufwand zu sein - mein Zustand ist groß und kompliziert.
Hier fand ich INotifyPropertyChanged besser, um Eigenschaften aus der Geschäftslogik für die GUI verfügbar zu machen.
Davon abgesehen erwies sich DP als einfache Lösung, wenn ich ein benutzerdefiniertes GUI-Widget benötigte, um eine Eigenschaft verfügbar zu machen, und wenn Änderungen an dieser Eigenschaft Auswirkungen auf andere GUI-Widgets hatten.
Dort fand ich DP nützlich für die Benachrichtigung von GUI zu GUI.
quelle
.NET 4.0 verfügt über System.Xaml.dll, sodass Sie nicht von einem beliebigen Framework abhängig sein müssen, um es zu verwenden. Siehe Rob Relyeas Beitrag über seine PDC-Sitzung.
Meine Einstellung
XAML ist eine Sprache zur Beschreibung von Objekten, und WPF ist ein Framework, dessen beschriebene Objekte UI-Elemente sind.
Ihre Beziehung ähnelt C #, einer Sprache zur Beschreibung von Logik, und .NET, einem Framework, das bestimmte Arten von Logik implementiert.
Der Zweck von XAML sind deklarative Objektgraphen. Die W * F-Technologien sind großartige Kandidaten für dieses Paradigma, aber XAML existiert unabhängig von ihnen.
XAML und das gesamte Abhängigkeitssystem wurden als separate Stapel für WF und WPF implementiert, wahrscheinlich um die Erfahrung verschiedener Teams zu nutzen, ohne eine Abhängigkeit (kein Wortspiel beabsichtigt) zwischen ihnen zu schaffen.
quelle
Abhängigkeitseigenschaften sind der Klebstoff für die Erstellung benutzerdefinierter Steuerelemente. Wenn Sie Intelli-sense verwenden möchten, um Ihre Eigenschaften zur XAML-Entwurfszeit im Eigenschaftenfenster anzuzeigen, müssen Sie Abhängigkeitseigenschaften verwenden. INPC zeigt zur Entwurfszeit niemals eine Eigenschaft im Eigenschaftenfenster an.
quelle
Es scheint, dass Abhängigkeitseigenschaften in Steuerelementen verwendet werden sollten, die Sie erstellen, z. B. Schaltflächen. Um Eigenschaften in XAML zu verwenden und alle WPF-Funktionen zu verwenden, müssen diese Eigenschaften Abhängigkeitseigenschaften sein.
Ihr ViewModel ist jedoch besser dran, wenn Sie INotifyPropertyChanged verwenden. Wenn Sie INotifyPropertyChanged verwenden, können Sie bei Bedarf über eine Getter- / Setter-Logik verfügen.
Ich empfehle, Josh Smiths Version einer Basisklasse auf ein ViewModel zu überprüfen, das bereits INotifyPropertyChanged implementiert:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
Ich denke, dies ist ein hervorragendes Beispiel für die Erstellung eines ViewModel.
quelle
Ich denke, DependencyProperty und INotifyPropertyChanged werden für zwei verschiedene Dinge in Binding verwendet: die erste, um eine Eigenschaft als Ziel einer Bindung zu aktivieren und die Eingabe von einer anderen Eigenschaft zu erhalten (verwenden Sie {Binding ...}, um die Eigenschaft festzulegen), die letzte wenn Sie möchten, dass der Wert einer Eigenschaft als Quelle einer Bindung verwendet wird (Name im Bindungspfadausdruck). Die Wahl ist also nur technisch.
quelle
Ich bevorzuge einen direkteren Ansatz, über den ich in Presentation Model Without INotifyPropertyChanged gebloggt habe . Mithilfe einer Alternative zur Datenbindung können Sie ohne Buchhaltungscode direkt an CLR-Eigenschaften binden. Sie schreiben einfach alten .NET-Code in Ihr Ansichtsmodell und dieser wird aktualisiert, wenn sich Ihr Datenmodell ändert.
quelle
INotifyPropertyChanged
,PropertyDescriptor
verwendet werden, was bewirkt , dass SpeicherlecksEs gibt nur eine Sache, warum Sie eine bevorzugen sollten
DependencyObject
- Bindung funktioniert besser. Versuchen Sie einfach ein Beispiel mit einemListBox
undTextBox
, füllen Sie die Liste mit Daten aus derINotifyPropertyChanged
Eigenschaft vs.DependencyProperty
und bearbeiten Sie das aktuelle Element ausTextBox
...quelle
Wenn Sie Eigenschaften anderen Steuerelementen aussetzen möchten, müssen Sie Abhängigkeitseigenschaften verwenden ... Aber viel Glück, denn es dauert eine Weile, bis sie es herausfinden ...
quelle