Ich stelle mir das so vor:
Ansichten sind, wie Sie sagen, dumm. Josh Smith, Autor des bahnbrechenden und oft verlinkten MSDN-Artikel über MVVM, hat gesagt, dass Views "die Kleider sind, die die Daten tragen". Ansichten enthalten eigentlich nie Daten oder manipulieren sie direkt, sie sind nur an Eigenschaften und Befehle Ihrer Viewmodels gebunden.
Modelle sind Objekte, die modellieren den Bereich Ihrer Anwendung wie bei Geschäftsobjekten. Ist Ihre Anwendung ein Musikgeschäft? Vielleicht sind Ihre Modellobjekte Künstler, Alben und Songs. Handelt es sich bei Ihrer Anwendung um einen Organigrammbrowser? Vielleicht sind Ihre Modellobjekte Manager und Mitarbeiter. Diese Modellobjekte haben nichts mit der visuellen Darstellung zu tun und stehen nicht einmal in direktem Zusammenhang mit der Anwendung, in die sie eingefügt werden - Ihre Modellobjekte sollten als eine Familie von Objekten, die eine Art von Domäne repräsentieren, für sich allein stehen. Die Modellschicht enthält auch typischerweise Dinge wie Service Accessors.
Dies bringt uns zu den Ansichtsmodellen. Was sind diese? Sie sind Objekte, die modellieren eine GUI-Anwendung Das heißt, sie stellen Daten und Funktionen zur Verfügung, die von den Ansichten genutzt werden können. Sie definieren die Struktur und das Verhalten der eigentlichen Anwendung, die Sie erstellen. Für die Modellobjekte ist die Domäne die von Ihnen gewählte Domäne (Musikgeschäft, Organigramm-Browser usw.), für die Ansichtsmodelle ist die Domäne jedoch eine grafische Anwendung. Ihre Viewmodels kapseln das Verhalten und die Daten von allem, was Ihre Anwendung tut. Sie stellen Objekte und Listen als Eigenschaften zur Verfügung, ebenso wie Dinge wie Befehle. Ein Befehl ist nur ein Verhalten (im einfachsten Fall ein Methodenaufruf), das in ein Objekt verpackt ist, das es mit sich führt - dieser Gedanke ist wichtig, weil Ansichten durch Datenbindung gesteuert werden, die visuelle Steuerelemente an Objekte bindet. In MVVM geben Sie einer Schaltfläche keine Click-Handler-Methode, sondern binden sie an ein Command-Objekt (das von einer Eigenschaft in einem Viewmodel bereitgestellt wird), das die Funktionalität enthält, die Sie ausführen möchten, wenn Sie auf die Schaltfläche klicken.
Für mich waren die folgenden Punkte am verwirrendsten:
- Obwohl es sich bei den Viewmodels um Modelle einer grafischen Anwendung handelt, verweisen sie nicht direkt auf visuelle Konzepte oder verwenden diese. Sie wollen zum Beispiel keine Verweise auf Windows-Steuerelemente in Ihren ViewModels - diese Dinge gehören in die Ansicht. ViewModels stellen einfach Daten und Verhaltensweisen für Steuerelemente oder andere Objekte zur Verfügung, die mit ihnen verbunden werden. Haben Sie zum Beispiel eine Ansicht mit einer ListBox darin? Ihr ViewModel wird mit ziemlicher Sicherheit eine Art von Sammlung enthalten. Verfügt Ihr View über Schaltflächen? Ihr Viewmodel wird mit ziemlicher Sicherheit einige Befehle enthalten.
- Es gibt einige Arten von Objekten, die als "Ansichtsmodelle" betrachtet werden können. Die einfachste Art von Viewmodel ist eines, das direkt ein Steuerelement oder einen Bildschirm in einer 1:1-Beziehung darstellt, wie z. B. "Bildschirm XYZ hat ein Textfeld, ein Listenfeld und drei Schaltflächen, also braucht das Viewmodel eine Zeichenkette, eine Sammlung und drei Befehle." Eine andere Art von Objekten, die in die Viewmodel-Schicht passt, ist ein Wrapper um ein Modellobjekt, der ihm Verhalten verleiht und es für eine Ansicht besser nutzbar macht - hier kommen Sie zu den Konzepten der "dicken" und "dünnen" Viewmodel-Schichten. Eine "dünne" Viewmodel-Schicht besteht aus einer Reihe von Viewmodels, die Ihre Modellobjekte direkt den Views zur Verfügung stellen, d.h. die Views binden sich direkt an Eigenschaften der Modellobjekte. Dies kann z. B. für einfache, schreibgeschützte Ansichten funktionieren, aber was ist, wenn Sie jedem Objekt ein Verhalten zuordnen möchten? Das wollen Sie nicht im Modell haben, weil das Modell nicht mit der Anwendung, sondern nur mit Ihrer Domäne verbunden ist. Sie können es in einem Objekt unterbringen, das Ihr Modellobjekt umhüllt und bindungsfreundlichere Daten und Verhaltensweisen bereitstellt. Dieses Wrapper-Objekt wird auch als Viewmodel bezeichnet und führt zu einer "dickeren" Viewmodel-Schicht, bei der Ihre Views nie direkt an eine Modellklasse gebunden sind. Sammlungen enthalten Viewmodels, die Modelle umhüllen, anstatt nur Modelle selbst zu enthalten.
Der Kaninchenbau geht noch tiefer - es gibt viele Idiome wie ValueConverters, die MVVM am Laufen halten, und es gibt eine Menge anzuwenden, wenn man anfängt, über Dinge wie Blendability, Testen und wie man Daten in der App weitergibt und sicherstellt, dass jedes Viewmodel Zugriff auf das Verhalten hat, das es braucht (hier kommt Dependency Injection ins Spiel), aber hoffentlich ist das oben Gesagte ein guter Anfang. Das Wichtigste ist, dass Sie Ihre Visuals, Ihre Domäne und die Struktur und das Verhalten Ihrer eigentlichen Anwendung als drei verschiedene Dinge betrachten.
3 Stimmen
Kann der Aussage nicht zustimmen, dass die Ansicht "nur weiß, wie man etwas präsentiert, das ihr übergeben wird". Die Ansicht nimmt Daten von der VM entgegen. Niemand gibt Daten an ihn weiter. Niemand weiß über View Bescheid. Dies ist ein wichtiger Unterschied zu MVP. In MVP (man kann es sich als eine einfache WPF-Anwendung mit Codebehind-Logik vorstellen, es ist ein MVP-Muster) ist der Codebehind ein Presenter, der Daten an die View weitergibt, wie Sie sagten.