10 Stimmen

M-V-VM, sickert das Modell nicht in die Ansicht?

Bei M-V-VM geht es, wie wir alle wissen, um die Trennung von Belangen. Bei 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 demonstrieren, das in vielen WPF-Anwendungen zu finden ist, und dann werde ich meinen Standpunkt darlegen:

Nehmen wir an, wir haben eine StockQuote-Anwendung, die eine Reihe von Kursen streamt und sie auf dem Bildschirm anzeigt. Normalerweise würde man das so machen:

StockQuote.cs : (Modell)

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

StockQuoteViewModel.cs : (ViewModel)

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

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

StockQuoteView.xaml (Ansicht)

<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 eine Art Dienst, der die ObservableCollection mit neuen StockQuotes füttern würde.

Meine Frage ist folgende: In dieser Art von Szenario ist die StockQuote als das Modell, und wir sind, dass die Ansicht durch die ViewModel's ObservableCollection aussetzen. Das bedeutet im Grunde, dass unsere View Kenntnis vom Model hat. Verstößt das nicht gegen das gesamte Paradigma von M-V-VM? Oder übersehe ich hier etwas....?

8voto

keithjgrant Punkte 11874

Ich bin mehr mit MVC als mit MVVM vertraut, aber es ist allgemein anerkannt, dass die Ansicht Kenntnisse über das Modell haben wird. Solange das Model keine Kenntnis von der View hat, ist das in Ordnung.

Wenn dies aus irgendeinem Grund ein Problem darstellt, sollten Sie sich die "passive Ansicht" ansehen, bei der die Ansicht nichts weiter weiß als die ihr zugeführten Rohdaten.

7voto

Oliver Hanappi Punkte 11642

In MVVM ist das Ansichtsmodell etwas zwischen der Ansicht und dem Modell, das die Daten aus dem Modell in einer Weise darstellt, die von der Ansicht leicht verarbeitet werden kann. In einer strikten MVVM-Anwendung weiß die Ansicht nichts über das Modell, sondern nur über das Ansichtsmodell.

In Ihrem konkreten Beispiel sollte das View-Modell nicht aufgerufen werden StockQuoteViewModel sondern StockQuotesViewModel (achten Sie auf den Plural), da das Ansichtsmodell viele Aktienkurse über eine spezielle UI-Sammlung bereitstellt, die von der Ansicht leicht zu handhaben ist (da ObservableCollection<T> implementiert INotifyCollectionChanged<T> ). Der Typ der Elemente in der Sammlung sollte ein View Model sein (z. B. StockQuoteViewModel ), das die Daten eines einzelnen StockQuote-Objekts offenlegt. In einem solchen View Model können Sie Logik hinzufügen, wie z.B. das Hinzufügen eines $ -Symbol an Price und so weiter.

Oft ist es einfacher, einige Modellobjekte in einem View Model darzustellen, aber der richtige Weg wäre, für jede Modellklasse ein View Model zu erstellen.

Mit freundlichen Grüßen,
Oliver Hanappi

3voto

majocha Punkte 1151

Nein. Sie geben StockQuote nicht frei. Sie spezifizieren lediglich eine (lose typisierte) Schnittstelle in der Ansicht. Die Ansicht kennt nur zwei Eigenschaften: Symbol und Preis. Sie können StockQuote problemlos durch etwas anderes ersetzen, solange es diese Eigenschaften implementiert.

3voto

zendar Punkte 13036

Video ansehen: Jason Dolinger über MVVM . Sie wird Ihre Frage beantworten.

Siehe auch SO Frage wpf mvvm verwirrung für zusätzliche Ressourcen.

1voto

Dan Bryant Punkte 27022

Nach meinem Verständnis sind ViewModels für Models das, was Properties für Fields sind. Das ist eine sehr lose Analogie, aber sie impliziert, dass Sie nicht richtig isoliert sind, wenn Ihre Ansicht direkt auf Ihr Modell zugreift. Genau wie bei trivialen Eigenschaften in einer Klasse, die private Felder umhüllen, kommt es beim Umhüllen relevanter Modelleigenschaften in ViewModel-Eigenschaften für die Verwendung durch die Ansicht zu einer Menge Duplizierung und Boilerplate-Code. Das ist etwas, das mich an diesem Muster stört, und ich bin mir immer noch nicht sicher, ob die Vorteile die Aufblähung wert sind.

In diesem speziellen Beispiel denke ich, dass es übertrieben wäre, eine VM für jede StockQuote-Instanz zu erstellen, da Sie wahrscheinlich keine signifikante Logik für die Ansicht ausführen, die eine einzelne StockQuote darstellt. Ich denke, dass es in diesen kleinen Fällen viel sauberer und wartbarer 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 Entscheidung von Fall zu Fall, ob dies von Vorteil ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X