practices - wpf validation mvvm




INotifyPropertyChanged vs. DependencyProperty in ViewModel (10)

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

.NET 4.0 wird System.Xaml.dll haben, so dass Sie keine Abhängigkeit von einem beliebigen Framework benötigen müssen, um es zu verwenden. Siehe Rob Relyeas Post über seine PDC-Sitzung.

Mein Nehmen

XAML ist eine Sprache zum Beschreiben von Objekten und WPF ist ein Framework, dessen beschriebene Objekte UI-Elemente sind.

Ihre Beziehung ähnelt C #, einer Sprache zum Beschreiben 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 Stacks 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.

Bei der Implementierung des ViewModel in einer WPF-Anwendung mit Model-View-ViewModel-Architektur scheint es zwei große Möglichkeiten zu geben, wie man es in eine Datenbank einbinden kann. Ich habe Implementierungen gesehen, die DependencyProperty für Eigenschaften verwenden, gegen die die View binden wird, und ich habe stattdessen ViewModel gesehen, das INotifyPropertyChanged implementiert INotifyPropertyChanged .

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


Abhängigkeitseigenschaften sind die Grundlage für die Erstellung benutzerdefinierter Steuerelemente. Wenn Sie daran interessiert sind, mit Intelli-Sense Ihre Eigenschaften im Eigenschaftenfenster zur XAML-Entwurfszeit anzuzeigen, müssen Sie die Abhängigkeitseigenschaften verwenden. INPC zeigt zur Entwurfszeit niemals eine Eigenschaft im Eigenschaftenfenster an.


Auch ich musste diese Entscheidung in letzter Zeit prüfen.

Ich stellte fest, dass der INotifyPropertyChanged-Mechanismus meinen Anforderungen besser entsprach, da ich dadurch meine GUI an ein vorhandenes Geschäftslogik-Framework kleben konnte, ohne den Zustand zu duplizieren. Der Rahmen, den ich benutzte, hatte sein eigenes Beobachtermuster und es war einfach, eine Benachrichtigungsstufe auf die nächste weiter zu leiten. Ich hatte einfach eine Klasse, die die Observer-Schnittstelle aus meinem Business-Logik-Framework und der INotifyPropertyChanged-Schnittstelle implementierte.

Mit DP können Sie nicht das Backend definieren, das den Status selbst speichert. Ich hätte .net eine Kopie jedes Staatspostens cachen lassen müssen, an den ich mich gebunden habe. Das schien wie ein unnötiger Overhead - mein Zustand ist groß und kompliziert.

Hier habe ich INotifyPropertyChanged besser gefunden, um Eigenschaften von der Geschäftslogik zur GUI freizulegen.

Da wo ich ein benutzerdefiniertes GUI-Widget brauchte, um eine Eigenschaft verfügbar zu machen, und dass Änderungen an dieser Eigenschaft sich auf andere GUI-Widgets auswirkten, erwies sich DP als einfache Lösung.

Also ich fand DP nützlich für GUI zu GUI Benachrichtigung.


Aus der Sicht der Expressivität genieße ich es sehr, Abhängigkeitseigenschaften zu verwenden und beim Gedanken an INotifyPropertyChanged . Abgesehen von den string Eigenschaftsnamen und möglichen Speicherlecks aufgrund von Ereignisabonnements ist INotifyPropertyChanged ein viel expliziterer Mechanismus.

Abhängigkeitseigenschaften implizieren "wenn dies geschieht" mithilfe leicht verständlicher statischer Metadaten. Es ist ein deklarativer Ansatz, der meine Stimme für Eleganz bekommt.


Es gibt nur eine Sache, warum man ein DependencyObject bevorzugen sollte - Binding wird besser funktionieren. ListBox TextBox ein Beispiel mit einer ListBox und TextBox , ListBox TextBox die Liste mit Daten aus der INotifyPropertyChanged Eigenschaft vs. DependencyProperty und bearbeiten Sie das aktuelle Element aus TextBox ...


Ich bevorzuge einen direkteren Ansatz, über den ich im Präsentationsmodell ohne INotifyPropertyChanged gebloggt habe . Mit einer Alternative zur Datenbindung können Sie ohne Buchhaltungscode direkt an CLR-Eigenschaften binden. Sie schreiben einfach reinen .NET-Code in Ihr Ansichtsmodell und es wird aktualisiert, wenn sich Ihr Datenmodell ändert.


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

Kurze Zusammenfassung:

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

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



Wenn Sie Eigenschaften anderen Steuerelementen zugänglich machen möchten, müssen Sie Abhängigkeitseigenschaften verwenden ... Aber viel Glück, weil sie eine Weile brauchen, um herauszufinden ...


INotifyPropertyChanged wenn verwendet, gibt Ihnen auch die Möglichkeit, mehr Logik im Code Ihrer Getter und Setter Ihrer Eigenschaften hinzuzufü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 SetValue und GetValue einfach aufrufen, b / c In anderen Teilen des Frameworks wird der Getter / Setter nicht aufgerufen, stattdessen ruft SetValue, GetValue direkt auf, also würde Ihre Eigenschaftslogik nicht funktionieren zuverlässig ausgeführt werden.

INotifyPropertyChanged mit INotifyPropertyChanged ein Ereignis:

public event PropertyChangedEventHandler PropertyChanged;

Und dann haben Sie einfach irgendeine Logik irgendwo in Ihrem Code, dann rufen Sie:

// ...
// 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 anderswo sein.





dependency-properties