2010-04-14 4 views
10

Der Punkt von M-V-VM, wie wir alle wissen, betrifft die Erstellung von Anliegen. In Mustern wie MVVM, MVC oder MVP besteht der Hauptzweck darin, die Ansicht von den Daten zu entkoppeln und dadurch flexiblere Komponenten zu erstellen. Ich werde zuerst ein sehr häufiges Szenario in vielen WPF-Anwendungen demonstrieren, und dann werde ich meinen Punkt machen:M-V-VM, leckt das Modell nicht in die Ansicht?

Sagen wir haben einige StockQuote-Anwendung, die eine Reihe von Angeboten streamt und zeigt sie auf dem Bildschirm. Normalerweise würde man dieses:

StockQuote.cs: (Modell)

public class StockQuote 
    { 
     public string Symbol { get; set; } 
     public double Price { get; set; } 
    } 

StockQuoteViewModel.cs: (Ansichtsmodell)

public class StockQuoteViewModel 
    { 
     private ObservableCollection<StockQuote> _quotes = new ObservableCollection<StockQuote>(); 

     public ObservableCollection<StockQuote> Quotes 
     { 
     get 
     { 
      return _quotes; 
     } 
     } 
    } 

StockQuoteView.xaml (View)

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    Title="Window1" Height="300" Width="300"> 
    <Window.DataContext> 
     <local:StockQuoteViewModel/> 
    </Window.DataContext> 
    <Window.Resources> 
     <DataTemplate x:Key="listBoxDateTemplate"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding Symbol}"/> 
       <TextBlock Text="{Binding Price}"/> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <ListBox ItemTemplate="{StaticResource listBoxDateTemplate}" ItemsSource="{Binding Quotes}"/> 
    </Grid> 
</Window> 

Und dann hätten Sie irgendeine Art von Service, der die ObservableCollection mit neuen StockQuotes füttern würde.

Meine Frage ist: In dieser Art von Szenario wird das StockQuote als das Modell betrachtet, und wir stellen das dem View durch die ObservableCollection des ViewModels zur Verfügung. Was im Grunde bedeutet, dass unser View das Modell kennt. Verstößt das nicht gegen das ganze Paradigma von M-V-VM? Oder vermisse ich hier etwas ....?

Antwort

3

Nein. Sie geben StockQuote nicht aus. Sie geben nur eine (locker typisierte) Schnittstelle in der Ansicht an. Die Ansicht kennt nur zwei Eigenschaften: Symbol und Preis. Sie können StockQuote ganz einfach durch andere ersetzen, solange es diese implementiert.

+0

Das ist ein guter Punkt, obwohl es auf der "lockeren" Natur von WPF Data Binding beruht. Wenn Sie einen Komponententest für die VM geschrieben haben, der sich auf die StockQuote-Sammlung stützte, würde sie jedoch beschädigt, wenn Sie die StockQuote-Klasse ändern. –

8

Ich bin vertrauter mit MVC als MVVM, aber es ist allgemein akzeptiert, dass die Ansicht Kenntnisse des Modells haben wird. Solange das Modell die Ansicht nicht kennt, ist dies in Ordnung.

Wenn dies aus irgendeinem Grund ein Problem ist, sehen Sie sich das "Passive View" -Design an, bei dem der View nichts weiter weiß als die ihm zugeführten Rohdaten.

+5

genau was ich schreiben wollte. Der Blick muss * etwas * über das Modell wissen, sonst worum geht es? – timdev

7

In MVVM ist das Ansichtsmodell etwas zwischen der Ansicht und dem Modell, das Daten aus dem Modell in einer Weise freigibt, die von der Ansicht einfach gehandhabt werden kann. In einer strikten MVVM-Anwendung kennt die Ansicht nichts über das Modell, sondern nur das Ansichtsmodell.

In Ihrem konkreten Beispiel sollte das View-Modell nicht StockQuoteViewModel aber StockQuotesViewModel (beachten Sie den Plural), weil das View-Modell durch eine bestimmte ui Sammlung viele Aktienkurse genannt wird aussetzt, die von der Ansicht einfach zu handhaben ist (weil ObservableCollection<T> implementiert INotifyCollectionChanged<T>). Der Typ von Elementen in der Sammlung sollte ein Ansichtsmodell sein (z. B. StockQuoteViewModel), das Daten von einem einzelnen StockQuote-Objekt verfügbar macht. In solch einem Ansichtsmodell können Sie eine Logik wie das Hinzufügen eines $-Symbols zu Price und so weiter hinzufügen.

Es ist oft einfacher, einige Modellobjekte in einem Ansichtsmodell verfügbar zu machen, aber die korrekte Methode besteht darin, für jede Modellklasse ein Ansichtsmodell zu erstellen.

Mit besten Grüßen,
Oliver Hanappi

0

Vielleicht habe ich das falsch, aber ist nicht die Idee des Ansichtsmodell vollständig um das Modell zu kapseln. Zum Beispiel haben Sie Aktienkurse, die der Ansicht ausgesetzt sind, aber sie sollten Eigenschaften zugeordnet werden, die für das Ansichtsmodell nativ sind, an die dann gebunden werden würde.Dies erfordert eine "Reinigung", die während der Übertragung von Daten zu dem Modell/der Ansicht erforderlich sein könnte.

So kennt die Ansicht nur das Viewmodel. Es bedeutet auch, dass, wenn das Modell nicht veraltet ist, es als eine Schnittstelle implementiert werden könnte und die Kopplung zwischen dem Ansichtsmodell weiter reduzieren würde.

1

Mein Verständnis ist, dass ViewModels zu Modellen als Eigenschaften zu Felder sind. Dies ist eine sehr lose Analogie, aber es bedeutet, dass Sie nicht richtig isoliert sind, wenn Ihre View direkt auf Ihr Modell zugreift. Genau wie bei trivialen Eigenschaften in einer Klasse, die private Felder umschließt, werden beim Kopieren relevanter Model-Eigenschaften in ViewModel-Eigenschaften für die Verwendung durch die View viele Duplikate und Codebausteine ​​ausgegeben. Das ist etwas, was mich mit diesem Muster stört und ich bin immer noch nicht entschieden, ob die Vorteile den Auftrieb wert sind.

In diesem speziellen Beispiel, ich denke, es wäre übertrieben, eine VM für jede StockQuote-Instanz zu erstellen, da Sie wahrscheinlich keine signifikante Logik für die Ansicht, die eine einzelne StockQuote darstellt. Ich denke, dass es in diesen kleinen Fällen viel sauberer und wartungsfreundlicher ist, einfach direkt an die Model-Klasse zu binden. Das Erstellen einer VM für den kleinen Fall würde die Kopplung reduzieren, aber es würde auch die Komplexität erhöhen, und ich denke, es ist eine Einzelfallentscheidung, ob dies vorteilhaft ist.

Verwandte Themen