Bei den meisten MVVM-Beispielen, die ich durchgearbeitet habe, wurde das Modell implementiert INotifyPropertyChanged
, aber im CommandSink-Beispiel von Josh Smith wird das ViewModel implementiertINotifyPropertyChanged
.
Ich stelle die MVVM-Konzepte immer noch kognitiv zusammen, daher weiß ich nicht, ob:
- Sie müssen das
INotifyPropertyChanged
in das ViewModel einfügen, umCommandSink
an die Arbeit zu gehen - Dies ist nur eine Abweichung von der Norm und es spielt keine Rolle
- Sie sollten immer das Modell implementieren lassen,
INotifyPropertyChanged
und dies ist nur ein Fehler, der korrigiert würde, wenn dies von einem Codebeispiel zu einer Anwendung entwickelt würde
Welche Erfahrungen haben andere mit MVVM-Projekten gemacht, an denen Sie gearbeitet haben?
c#
mvvm
inotifypropertychanged
Edward Tanguay
quelle
quelle
Antworten:
Ich würde ganz im Gegenteil sagen, ich habe
INotifyPropertyChanged
mein ViewModel immer auf mein ViewModel gesetzt - Sie möchten Ihr Modell wirklich nicht mit einer ziemlich WPF-spezifischen Funktion verschmutzen, wie zum BeispielINotifyPropertyChanged
, dass das Zeug im ViewModel sitzen sollte.Ich bin sicher, andere würden dem nicht zustimmen, aber so arbeite ich.
quelle
Ich bin mit dem Konzept, dass das Modell das nicht implementieren sollte, überhaupt nicht einverstanden
INotifyPropertyChanged
. Diese Schnittstelle ist nicht UI-spezifisch! Es informiert einfach über eine Änderung. In der Tat verwendet WPF dies häufig, um Änderungen zu identifizieren. Dies bedeutet jedoch nicht, dass es sich um eine Benutzeroberfläche handelt. Ich würde es mit dem folgenden Kommentar vergleichen: " Ein Reifen ist ein Autozubehör ". Sicher ist es das, aber Fahrräder, Busse usw. benutzen es auch. Zusammenfassend gesagt, nehmen Sie diese Schnittstelle nicht als UI-Sache.Dies bedeutet jedoch nicht unbedingt, dass ich glaube, dass das Modell Benachrichtigungen bereitstellen sollte. Als Faustregel sollte das Modell diese Schnittstelle nur implementieren, wenn dies erforderlich ist. In den meisten Fällen, in denen keine Serverdaten an die Client-App übertragen werden, kann das Modell veraltet sein. Aber wenn ich Finanzmarktdaten abhöre, sehe ich nicht, warum das Modell die Schnittstelle nicht implementieren kann. Was ist beispielsweise, wenn ich eine Nicht-UI-Logik wie einen Service habe, der beim Empfang eines Bid- oder Ask-Preises für einen bestimmten Wert eine Warnung ausgibt (z. B. per E-Mail) oder eine Bestellung aufgibt? Dies könnte eine mögliche saubere Lösung sein.
Es gibt jedoch verschiedene Wege, um Dinge zu erreichen, aber ich würde immer für Einfachheit eintreten und Redundanz vermeiden.
Was ist besser? Definieren von Ereignissen in einer Sammlung oder von Eigenschaftsänderungen im Ansichtsmodell und Weitergeben an das Modell oder Aktualisieren des Modells durch die Ansicht (über das Ansichtsmodell)?
Wenn Sie jemanden sehen, der behauptet, " Sie können dies oder das nicht ", ist dies ein Zeichen dafür, dass er nicht weiß, wovon er spricht.
Es hängt wirklich von Ihrem Fall ab und tatsächlich ist MVVM ein Framework mit vielen Problemen, und ich muss noch eine gemeinsame Implementierung von MVVM auf der ganzen Linie sehen.
Ich wünschte, ich hätte mehr Zeit, um die vielen Varianten von MVVM und einige Lösungen für häufig auftretende Probleme zu erklären - meistens von anderen Entwicklern, aber ich denke, ich muss es ein anderes Mal tun.
quelle
INotifyPropertyChanged
ist Teil desSystem.ComponentModel
Namespace für " Laufzeit- und Entwurfszeitverhalten von Komponenten und Steuerelementen ". NICHTINotifyPropertyChanged
in Modellen verwenden, sondern nur in ViewModels. Link zu Dokumenten: docs.microsoft.com/en-us/dotnet/api/system.componentmodelIn MV-VM wird das ViewModel immer (Modell nicht immer) implementiert
INotifyPropertyChanged
Schauen Sie sich die MV-VM-Projektvorlage / das Toolkit von an http://blogs.msdn.com/llobo/archive/2009/05/01/download-mv-vm-project-template-toolkit.aspx . Es verwendet das
DelegateCommand
für Befehle und sollte eine großartige Startvorlage für Ihre MV-VM-Projekte sein.quelle
Ich denke, MVVM hat einen sehr schlechten Namen und das Aufrufen des ViewModel als ViewModel führt dazu, dass viele ein wichtiges Merkmal einer gut gestalteten Architektur übersehen, nämlich einen DataController, der die Daten steuert, unabhängig davon, wer versucht, sie zu berühren.
Wenn Sie das View-Modell eher als DataController betrachten und eine Architektur implementieren, in der Ihr DataController das einzige Element ist, das die Daten berührt, würden Sie die Daten niemals direkt berühren, sondern immer den DataController verwenden. Der DataController ist nützlich für die Benutzeroberfläche, aber nicht unbedingt nur für die Benutzeroberfläche. Es ist für Business-Schicht, UI-Schicht, etc ...
Sie erhalten ein Modell wie dieses. Auch das Unternehmen sollte die Daten nur mit dem ViewModel berühren. Dann verschwindet dein Rätsel.
quelle
Dies hängt davon ab, wie Sie Ihr Modell implementiert haben. Mein Unternehmen verwendet Geschäftsobjekte, die den CSLA-Objekten von Lhotka ähnlich sind, und nutzt sie im
INotifyPropertyChanged
gesamten Geschäftsmodell umfassend.Unsere Validierungs-Engine ist stark darauf angewiesen, benachrichtigt zu werden, dass sich Eigenschaften durch diesen Mechanismus ändern, und sie funktioniert sehr gut. Wenn Sie eine andere Implementierung als Geschäftsobjekte verwenden, bei denen die Benachrichtigung über Änderungen für den Vorgang nicht so kritisch ist, stehen Ihnen möglicherweise andere Methoden zur Erkennung von Änderungen in Ihrem Geschäftsmodell zur Verfügung.
Wir haben auch Ansichtsmodelle, die die Änderungen aus dem Modell bei Bedarf weitergeben, aber die Ansichtsmodelle selbst hören sich die zugrunde liegenden Modelländerungen an.
quelle
Ich stimme Paulos Antwort zu, die Implementierung
INotifyPropertyChanged
in Models ist völlig akzeptabel und wird sogar von Microsoft vorgeschlagen -Es liegt zwar an Ihnen zu entscheiden, ob Sie diese Art der Implementierung wünschen oder nicht, aber denken Sie daran -
Entnommen aus - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx
Ich habe in einigen Projekten gearbeitet, in denen wir
INotifyPropertyChanged
unsere Modelle nicht implementiert haben, und aus diesem Grund standen wir vor vielen Problemen. In VM war eine unnötige Verdoppelung der Eigenschaften erforderlich, und gleichzeitig mussten wir das zugrunde liegende Objekt (mit aktualisierten Werten) aktualisieren, bevor wir es an BL / DL übergeben konnten.Sie werden insbesondere dann auf Probleme stoßen, wenn Sie mit der Sammlung Ihrer Modellobjekte (z. B. in einem bearbeitbaren Raster oder einer bearbeitbaren Liste) oder komplexen Modellen arbeiten müssen. Modellobjekte werden nicht automatisch aktualisiert und Sie müssen all das in Ihrer VM verwalten.
quelle
Aber manchmal (wie in diesem Link zum Präsentationstext ) ist das Modell ein Dienst, der die Anwendung mit einigen Daten online versorgt, und dann müssen Sie eine Benachrichtigung implementieren, dass neue Daten angekommen sind oder sich Daten aufgrund von Ereignissen geändert haben ...
quelle
Ich denke, die Antwort ist ziemlich klar, wenn Sie sich an die MV-VM halten möchten.
Siehe: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx
Im MVVM-Muster kapselt die Ansicht die Benutzeroberfläche und jede Benutzeroberflächenlogik, das Ansichtsmodell kapselt die Präsentationslogik und den Status und das Modell kapselt die Geschäftslogik und die Daten.
quelle
Ich würde in Ihrem ViewModel sagen. Es ist nicht Teil des Modells, da das Modell UI-unabhängig ist. Das Modell sollte "alles außer geschäftsunabhängig" sein.
quelle
Die Implementierung von INPC in Modellen kann verwendet werden, wenn die Modelle im ViewModel deutlich verfügbar gemacht werden. Im Allgemeinen handelt es sich beim ViewModel-Wrap der Modelle jedoch um seine eigenen Klassen, um die Modellkomplexität zu verringern (was für die Bindung nicht nützlich sein sollte). In diesem Fall sollte der INPC im ViewModel implementiert werden.
quelle
Ich benutze die
INotifyPropertyChange
Schnittstelle in einem Modell. Tatsächlich sollte eine Änderung der Modelleigenschaften nur von der Benutzeroberfläche oder einem externen Client ausgelöst werden.Ich habe mehrere Vor- und Nachteile festgestellt:
Vorteile
Notifier ist im Geschäftsmodell
Nachteile
Das Modell hat Eigenschaften (Menge, Rate, Provision, Gesamtleistung). Der Gesamtbetrag wird anhand von Menge, Rate und Provisionsänderung berechnet.
Bei Ladewerten von db wird die Berechnung der Gesamtleistung dreimal aufgerufen (Menge, Rate, Provision). Es sollte einmal sein.
Wenn rate, qty in der Business-Schicht zugewiesen ist, wird erneut ein Notifier aufgerufen.
Es sollte eine Option geben, um dies zu deaktivieren, möglicherweise in der Basisklasse. Entwickler könnten dies jedoch vergessen.
quelle
Ich denke, dass alles vom Anwendungsfall abhängt.
Wenn Sie ein einfaches Modell mit vielen Eigenschaften haben, können Sie INPC implementieren lassen. Mit einfach meine ich, dass dieses Modell eher wie ein POCO aussieht .
Wenn Ihr Modell komplexer ist und in einer interaktiven Modelldomäne lebt - Modelle, die auf Modelle verweisen, Ereignisse anderer Modelle abonnieren -, ist die Implementierung von Modellereignissen als INPC ein Albtraum.
Versetzen Sie sich in die Position einer Modellentität, die mit einigen anderen Modellen zusammenarbeiten muss. Sie haben verschiedene Veranstaltungen zu abonnieren. Alle von ihnen sind als INPC implementiert. Stellen Sie sich die Event-Handler vor, die Sie haben. Eine enorme Kaskade von if-Klauseln und / oder switch-Klauseln.
Ein weiteres Problem mit INPC. Sie sollten Ihre Apps so gestalten, dass sie auf Abstraktion und nicht auf Implementierung basieren. Dies erfolgt normalerweise über Schnittstellen.
Schauen wir uns zwei verschiedene Implementierungen derselben Abstraktion an:
Schauen Sie sich jetzt beide an. Was sagt Ihnen IConnectionManagerINPC? Dass sich einige seiner Eigenschaften ändern können. Sie wissen nicht, welcher von ihnen. Tatsächlich ist das Design so, dass nur IsConnected-Änderungen vorgenommen werden, da der Rest schreibgeschützt ist.
Im Gegenteil, die Absichten von IConnectionManager sind klar: "Ich kann Ihnen sagen, dass sich der Wert meiner IsConnected-Eigenschaft möglicherweise geändert hat."
quelle
Verwenden
INotifyPropertyChange
Sie einfach das in Ihrem Ansichtsmodell und nicht im Modell.Das Modell verwendet normalerweise das
IDataErrorInfo
, um die Validierungsfehler zu behandeln. Behalten Sie also einfach Ihr ViewModel bei und Sie befinden sich direkt auf Ihrer MVVM-Straße.quelle
Angenommen, die Referenz des Objekts in Ihrer Ansicht ändert sich. Wie benachrichtigen Sie alle zu aktualisierenden Eigenschaften, um die richtigen Werte anzuzeigen? Das Aufrufen
OnPropertyChanged
Ihrer Ansicht für alle Objekteigenschaften ist aus meiner Sicht Müll.Also , was ich tue , ist das Objekt selbst zu lassen , jemanden benachrichtigen , wenn ein Wert in einer Eigenschaft ändert, und meiner Meinung nach mir Bindungen verwenden wie
Object.Property1
,Object.Property2
und so weiter. Auf diese Weise mache ich es einfach, wenn ich nur das Objekt ändern möchte, das derzeit in meiner Ansicht verwaltet wirdOnPropertyChanged("Object")
.Um Hunderte von Benachrichtigungen während des Ladens von Objekten zu vermeiden, habe ich einen privaten booleschen Indikator, den ich beim Laden auf true setze, der vom Objekt überprüft wird
OnPropertyChanged
und nichts bewirkt.quelle
Normalerweise implementiert ViewModel das
INotifyPropertyChanged
. Modell kann alles sein (XML-Datei, Datenbank oder sogar Objekt). Das Modell wird verwendet, um die Daten dem Ansichtsmodell zu übergeben, das sich an die Ansicht weitergibt.siehe hier
quelle
Ich denke, das Viewmodel implementiert
INotifyPropertyChange
und das Modell könnte Benachrichtigungen auf einer anderen "Ebene" verwenden.Beispiel: Mit einem Dokumentendienst und einem Dokumentobjekt haben Sie ein documentChanged-Ereignis, das ein Ansichtsmodell abhört, um die Ansicht zu löschen und neu zu erstellen. Im Bearbeitungsansichtsmodell haben Sie eine Eigenschaftsänderung für die Eigenschaften des Dokuments, um die Ansichten zu unterstützen. Wenn der Dienst beim Speichern des Dokuments (Aktualisierung des Änderungsdatums, des letzten Benutzers usw.) viel tut, kommt es leicht zu einer Überladung von Ereignissen, bei denen sich die Eigenschaft geändert hat, und es reicht aus, nur ein Dokument zu ändern.
Aber wenn Sie es
INotifyPropertyChange
in Ihrem Modell verwenden, ist es meiner Meinung nach eine gute Praxis, es in Ihrem Ansichtsmodell weiterzuleiten, anstatt es direkt in Ihrer Ansicht zu abonnieren. In diesem Fall müssen Sie nur das Ansichtsmodell ändern, wenn sich die Ereignisse in Ihrem Modell ändern, und die Ansicht bleibt unberührt.quelle
Alle Eigenschaften, die an meine Ansicht gebunden sind, befinden sich in meinen ViewModel (s). Daher sollten sie die INotifyPropertyChanged-Schnittstelle implementieren. Daher erhält die Ansicht alle Änderungen.
[Mit dem MVVM Light-Toolkit habe ich sie von ViewModelBase erben lassen.]
Das Modell enthält die Geschäftslogik, hat jedoch nichts mit der Ansicht zu tun. Daher ist die INotifyPropertyChanged-Schnittstelle nicht erforderlich.
quelle