2011-01-12 13 views
3

Ich habe meine MVVM und das Modell besteht aus einer Reihe von verwandten Klassen, aber für diese Frage konzentrieren wir uns auf nur vier.DependencyProperty Analog für WPF MVVM Modell

GrandParentModel, ParentModel, ChildModel und Contact.

Diese Typen erben alle von ModelBase, auf dem eine Implementierung von INotifyPropertyChanged ausgeführt wird.

So hat jedes der drei Modelle eine Kontakteigenschaft. Wenn Child keine Eigenschaft hat, sollte es nach Parent suchen, und wenn Parent leer ist, wird es nach GrandParent aussehen. Wenn sich der Kontakt auf der Großelternebene ändert, möchte ich, dass alle abhängigen Personen, dh alle Untereltern und ihre Kinder, ein PropertyChanged-Ereignis für ihren Kontakt auslösen.

Ich denke, alles, was ich tun werde, wird durch das DependencyProperty-System unterstützt, aber ich möchte das nicht verwenden, da dies mein Modell, Trennung von Bedenken und all das ist. Also stelle ich eine Mini-Implementierung zusammen, die alles in Ordnung ist.

Meine Frage ist, ist jemand diesen Weg schon einmal gegangen und gibt es irgendetwas, worüber ich mir in der Zukunft Sorgen machen sollte? Meine Spidey-Senses kribbeln und ich weiß nicht warum.

Dank Ian

Edit: Die Beziehung zwischen den hier Objekte ist, dass ein Großelternteil eine beliebige Anzahl von Eltern hat eine beliebige Anzahl von Kindern hat. Mein aktuelles Modell hat auf jedem eine Eigenschaft, die auf das Elternelement zeigt (bei Großeltern null), und ein Eltern-/Großelternteil hat eine Sammlung von Kindobjekten.

+0

Könnten Sie bitte ein Beispiel für die Klassenhierarchie/Beziehungen hinzufügen? (vorzugsweise mit Pseudocode) Sind sie "ist ein" oder "hat ein" Beziehungen? Komplexe Eigenschaften oder Sammlungen? usw. –

+0

In diesem Fall enthält meine ModelBase eine Elterneigenschaft, die bei der Erstellung auf das Elternobjekt gesetzt wird. Ich werde eine vollständige Lösung veröffentlichen, wenn ich die Codelänge auf etwas reduzieren kann, das hier passt. Ich habe oben ein kleines Edit hinzugefügt, die Struktur ist nicht in Stein, um ehrlich zu sein. – Ian

Antwort

2

Ich bin diesen Weg gegangen, und es ist nicht schön. Im Grunde müssen Sie das PropertyChanged Ereignis von ParentModel von Ihrem ChildModel unterzeichnen. Sie müssen aufpassen, wenn Ihr Kind die Eltern wechseln kann. Wenn Sie dann aus der Sicht des Kindes über eine Änderung des Elternteils informiert werden, müssen Sie Ihr eigenes PropertyChanged-Ereignis für das Kind auslösen. Es wird hässlich, weil Sie mit hängenden Ereignishandlern enden können, die Sie vergessen haben, aufzuräumen.

Eine bessere Methode wäre, Ihr eigenes modellspezifisches Analog zu DependencyProperty zu erstellen. Im Prinzip in Ihrem Konstruktor ChildModel "deklarieren" Sie diese Eigenschaft Contact delegiert auf Eigenschaft Contact des Objekts Parent, wenn null. Verwenden Sie dazu eine kleine Hilfsklasse, die das Ereignis PropertyChanged auf dem Objekt ParentModel beobachtet, und führen Sie gegebenenfalls ein Ereignis PropertyChanged auf dem untergeordneten Element aus. Achten Sie auch darauf, dass die Eigenschaft Parent für das Kind geändert wird.

Sie könnten den MVVM Light-Nachrichtenbus verwenden. Lassen Sie das Großelternteil und das Elternteil alle eine Nachricht senden, wenn sich ihre Contact Eigenschaft ändert. Lassen Sie das Kind auf diese Nachrichten hören. Wenn es eine Nachricht erhält, überprüfen Sie, ob es mit seinem eigenen Eltern- oder Großelternteil übereinstimmt, und richten Sie ggf. ein Ereignis PropertyChanged ein. Dies ist besser als die oben genannte Methode, da Sie nicht darauf achten müssen, wenn sich Ihr Eltern- oder Großelternteil ändert. Sie haben weniger wahrscheinlich Bugs. Es verwendet auch schwache Referenzen, so dass es die Objekte nicht auf die Art und Weise wie Event-Handler halten.

Nun, was ich getan habe ist weg von meiner Modellobjekte zu implementieren INotifyPropertyChanged. Ich führte eine Presenter Schicht zwischen meinem Model und meinem ViewModel ein. Die Presenter konstruiert tatsächlich ein ViewModel aus kleinen ViewModel "Widgets" (ein Widget könnte zum Beispiel ein ChangeValue<T> Widget sein).Ich habe eine Rules-Engine, die dem Presenter wie ein ViewModel aus Widgets für ein bestimmtes Modell zusammengestellt wird. Die Presenter behandelt alle Benutzereingaben (im Grunde genommen ein Lambda gegen das Model), aber da sie weiß, dass gerade eine Benutzeraktion stattgefunden hat, weiß sie, dass sich etwas im Model geändert haben könnte. Nachdem die Aktion Modell abgeschlossen ist, kopiert es alle Daten aus dem Modell in das ViewModel. Das ViewModel prüft die eingehenden Daten und löst ein PropertyChanged-Ereignis aus, wenn sich das Feld tatsächlich ändert. Offensichtlich ist dies der komplizierteste Weg, es zu tun, aber es gibt Ihnen ein wirklich sauberes Modell und weder das ViewModel noch der Presenter enthalten irgendeine Model (Domain/Business) -Logik.

+0

Interessant. Ich habe eine Dependency-Eigenschaft wie die Klasse zusammengestellt. Ich werde morgen eine gekürzte Version veröffentlichen, wenn ich wieder vor dem Code bin. Ich mag dein Presenter-Konzept, ich habe angefangen, etwas ähnliches zu tun, denke ich, also ist es gut zu hören, was du sagst, es wird mir helfen, denke ich :) – Ian

+0

Okie dokie Ich habe eine Lösung, aber ich denke es wird zu lange sein, hier zu posten. Ich lege einen Blogpost zusammen und poste die URL dafür, wenn das erlaubt ist. – Ian

+0

@Ian - Ich würde das gerne sehen. Bitte posten Sie es. –