it-swarm.com.de

INotifyPropertyChanged vs. DependencyProperty in ViewModel

Wenn Sie das ViewModel in eine WPF-Anwendung mit Model-View-ViewModel-Architektur implementieren, stehen anscheinend zwei Hauptoptionen zur Verfügung, um die Datenbindung zu ermöglichen. Ich habe Implementierungen gesehen, die DependencyProperty für Eigenschaften verwenden, an die die Ansicht gebunden werden soll, und ich habe stattdessen gesehen, dass ViewModel INotifyPropertyChanged implementiert.

Meine Frage ist, wann sollte ich eine der anderen vorziehen? Gibt es Leistungsunterschiede? Ist es wirklich eine gute Idee, die ViewModel-Abhängigkeiten an WPF zu übergeben? Was muss ich bei der Designentscheidung noch beachten?

347
bitbonk

Kent hat einen interessanten Blog zu diesem Thema geschrieben: View Models: POCOs versus DependencyObjects .

Kurze Zusammenfassung:

  1. DependencyObjects werden nicht als serialisierbar markiert
  2. Die DependencyObject-Klasse überschreibt und versiegelt die Methoden Equals () und GetHashCode ()
  3. Ein DependencyObject hat eine Thread-Affinität - auf es kann nur auf dem Thread zugegriffen werden, auf dem es erstellt wurde

Ich bevorzuge den POCO-Ansatz. Eine Basisklasse für PresentationModel (auch ViewModel genannt), die die INotifyPropertyChanged-Schnittstelle implementiert, finden Sie hier: http://compositeextensions.codeplex.com

210
jbe

Laut dem WPF-Leistungshandbuch erzielen DependencyObjects definitiv eine bessere Leistung als POCOs, die INotifyPropertyChanged implementieren:

http://msdn.Microsoft.com/en-us/library/bb613546.aspx

37
James Ashley

Die Auswahl hängt vollständig von Ihrer Geschäftslogik und der Abstraktionsebene der Benutzeroberfläche ab. Wenn Sie keine gute Trennung wünschen, funktioniert DP für Sie.

DependencyProperties sind hauptsächlich auf der VisualElements-Ebene anwendbar. Daher ist es keine gute Idee, wenn wir für jede unserer Geschäftsanforderungen viele DPs erstellen. Außerdem sind die Kosten für DP höher als für INotifyPropertyChanged. Beim Entwerfen von WPF/Silverlight versuchen Sie, Benutzeroberfläche und ViewModel vollständig getrennt zu gestalten, sodass wir zu jedem Zeitpunkt die Steuerelemente für Layout und Benutzeroberfläche ändern können (basierend auf Thema und Stilen).

Lesen Sie auch diesen Beitrag - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . Der Link enthält zahlreiche Verweise auf das Model-View-ViewModel-Muster, das für diese Diskussion sehr relevant ist.

27
Jobi Joy

Vom Standpunkt der Ausdruckskraft aus genieße ich es, Abhängigkeitseigenschaften zu verwenden und bei dem Gedanken an INotifyPropertyChanged zusammenzucken. Abgesehen von den string -Eigenschaftsnamen und möglichen Speicherverlusten aufgrund von Ereignisabonnements ist INotifyPropertyChanged ein viel expliziterer Mechanismus.

Abhängigkeitseigenschaften setzen voraus, dass "wann dies getan wird" und leicht verständliche statische Metadaten verwendet werden. Es ist ein deklarativer Ansatz, der meine Stimme für Eleganz erhält.

19
Bryan Watts

Abhängigkeitseigenschaften sollen die Bindung (als Ziel) von UI-Elementen unterstützen, nicht als Quelle für die Datenbindung. Hier kommt INotifyProperty ins Spiel. Aus reiner Sicht sollten Sie DP nicht für 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 Quelleneigenschaft Änderungsbenachrichtigungen unterstützen, die an das Bindungssystem und damit an das Ziel weitergegeben werden. Bei benutzerdefinierten CLR-Bindungsquellen muss die Eigenschaft INotifyPropertyChanged unterstützen. 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

16
Nick Hermans

INotifyPropertyChanged gibt Ihnen bei Verwendung auch die Möglichkeit, mehr Logik in den Code Ihrer Getter und Setter Ihrer Eigenschaften einzufügen.

DependencyProperty Beispiel:

public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );

public String Name
{
    set { SetValue( NameProperty, value ); }
    get { return ( String ) GetValue( NameProperty ); }
}

In Ihrem Getter und Setter können Sie einfach SetValue bzw. GetValue aufrufen. In anderen Teilen des Frameworks wird der Getter/Setter nicht b/c aufgerufen, sondern direkt SetValue, GetValue, sodass Ihre Eigenschaftslogik dies nicht tut zuverlässig ausgeführt werden.

Definieren Sie mit INotifyPropertyChanged ein Ereignis:

public event PropertyChangedEventHandler PropertyChanged;

Und dann haben Sie einfach eine beliebige Logik irgendwo in Ihrem Code und rufen dann auf:

// ...
// Something cool...
// ...

if( this.PropertyChanged != null )
{
    PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}

// More cool stuff that will reliably happen...

Dies könnte in einem Getter/Setter oder irgendwo anders sein.

16
Adam

Auch ich musste diese Entscheidung in letzter Zeit berücksichtigen.

Ich stellte fest, dass der INotifyPropertyChanged-Mechanismus meinen Anforderungen besser entsprach, da ich meine GUI mit einem vorhandenen Geschäftslogik-Framework verbinden 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 Observer-Schnittstelle aus meinem Geschäftslogik-Framework und der INotifyPropertyChanged-Schnittstelle implementierte.

Mit DP können Sie das Backend, das den Zustand speichert, nicht selbst definieren. Ich hätte .net eine Kopie jedes Zustands zwischenspeichern lassen müssen, an den ich gebunden war. Dies schien ein unnötiger Aufwand zu sein - mein Zustand ist groß und kompliziert.

Daher fand ich INotifyPropertyChanged hier besser, um Eigenschaften aus der Geschäftslogik für die GUI verfügbar zu machen.

Das heißt, wo ich ein benutzerdefiniertes GUI-Widget brauchte, um eine Eigenschaft freizulegen und Änderungen an dieser Eigenschaft andere GUI-Widgets zu beeinflussen, erwies sich DP als die einfache Lösung.

Daher fand ich DP nützlich für die GUI-zu-GUI-Benachrichtigung.

7
morechilli

Ist es wirklich eine gute Idee, die ViewModel-Abhängigkeiten an WPF zu übergeben?

.NET 4.0 verfügt über System.Xaml.dll, sodass Sie nicht auf ein beliebiges Framework angewiesen sein müssen, um es zu verwenden. Siehe Rob Relyeas Post über seine PDC Session.

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 hervorragende Kandidaten für dieses Paradigma, aber XAML existiert unabhängig davon.

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.

6
Bryan Watts

Abhängigkeitseigenschaften sind die Grundlage 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.

5
John Peters

Anscheinend sollten Abhängigkeitseigenschaften in Steuerelementen verwendet werden, die Sie erstellen, z. B. Schaltflächen. Um Eigenschaften in XAML zu verwenden und alle WPF-Features zu verwenden, müssen diese Eigenschaften Abhängigkeitseigenschaften sein.

Ihr ViewModel ist jedoch mit INotifyPropertyChanged besser dran. Wenn Sie INotifyPropertyChanged verwenden, können Sie bei Bedarf über eine Get-/Setter-Logik verfügen.

Ich empfehle, Josh Smiths Version einer Basisklasse auf ein ViewModel zu prü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 ein ViewModel.

4
timothymcgrath

Ich denke, dass DependencyProperty und INotifyPropertyChanged für zwei verschiedene Dinge in Binding verwendet werden: die erste, um eine Eigenschaft als Ziel einer Bindung zu aktivieren und die Eingabe einer anderen Eigenschaft zu empfangen (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 Bindungspfad-Ausdruck). Die Wahl ist also nur technisch.

4
Domnik

Es gibt nur einen Grund, warum Sie ein DependencyObject bevorzugen sollten: Die Bindung funktioniert besser. Probieren Sie einfach ein Beispiel mit ListBox und TextBox aus, füllen Sie die Liste mit Daten aus der Eigenschaft INotifyPropertyChanged gegenüber DependencyProperty und bearbeiten Sie das aktuelle Element aus TextBox...

3
ramos

Ich bevorzuge einen direkteren Ansatz, über den ich in Presentation Model Without INotifyPropertyChanged gebloggt habe. Mit 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.

3
Michael L Perry

Wenn Sie Eigenschaften für andere Steuerelemente verfügbar machen möchten, müssen Sie die Abhängigkeitseigenschaften verwenden.

1
JWP