2010-04-14 3 views
10

Le point de M-V-VM comme nous le savons tous est au sujet de la speraration des soucis. Dans les modèles tels que MVVM, MVC ou MVP, l'objectif principal est de découpler la vue des données afin de créer des composants plus flexibles. Je vais d'abord montrer un scénario très courant dans de nombreuses applications WPF, puis je ferai valoir mon point de vue:M-V-VM, le modèle ne fuit-il pas dans la vue?

Disons que nous avons une application StockQuote qui diffuse un ensemble de citations et les affiche à l'écran. En règle générale, vous auriez ceci:

StockQuote.cs: (Modèle)

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 (Voir)

<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> 

Et puis vous auriez un genre de service qui alimenterait ObservableCollection avec de nouvelles StockQuotes.

Ma question est la suivante: Dans ce type de scénario, StockQuote est considéré comme le modèle, et nous l'exposons à la vue à travers ObservableCollection du ViewModel. Ce qui signifie fondamentalement, notre vue a la connaissance du modèle. Cela ne viole-t-il pas tout le paradigme de M-V-VM? Ou est-ce que je manque quelque chose ici ...?

Répondre

3

Non. Vous n'exposez pas StockQuote. Vous ne spécifiez qu'une interface (faiblement typée) dans la vue. La vue ne connaît que deux propriétés: Symbol et Price. Vous pouvez facilement remplacer StockQuote avec n'importe quoi d'autre tant qu'il implémente ceux-ci.

+0

C'est un bon point, bien qu'il repose sur la nature «lâche» de la liaison de données WPF. Cependant, si vous aviez écrit un test unitaire pour la machine virtuelle qui dépendait de la collection StockQuote, elle se briserait si vous changiez la classe StockQuote. –

8

Je suis plus familier avec MVC qu'avec MVVM, mais il est généralement accepté que le View connaisse le Modèle. Tant que le modèle n'a aucune connaissance de la vue, c'est correct. Si cela vous préoccupe vraiment, quelle qu'en soit la raison, consultez le design "Passive View", où la vue ne sait rien de plus que les données brutes qui lui sont fournies.

+5

exactement ce que j'étais sur le point de taper. La vue doit savoir * quelque chose * sur le modèle, sinon de quoi s'agit-il? – timdev

7

Dans MVVM, le modèle de vue est quelque chose entre la vue et le modèle qui expose les données du modèle d'une manière qui peut être manipulée facilement par la vue. Dans une application MVVM stricte, la vue ne connaît pas le modèle, mais seulement le modèle de vue.

Dans votre exemple concret du modèle de vue ne doit pas être appelé StockQuoteViewModel mais StockQuotesViewModel (attention au pluriel), car le modèle de vue expose de nombreuses cotations boursières par une collection ui spécifique qui est facile à manipuler par la vue (parce que ObservableCollection<T> implémente INotifyCollectionChanged<T>). Le type d'éléments de la collection doit être un modèle de vue (par exemple, StockQuoteViewModel) qui expose les données d'un seul objet StockQuote. Dans un tel modèle de vue, vous pouvez ajouter une logique comme l'ajout d'un $ -symbol à Price et ainsi de suite.

Il est souvent plus facile d'exposer certains objets de modèle dans un modèle de vue, mais la méthode correcte consiste à créer un modèle de vue pour chaque classe de modèle.

Cordialement,
Oliver Hanappi

0

Peut-être que je me trompe, mais est pas l'idée du viewmodel pour encapsuler complètement le modèle. Par exemple, vous avez des cotations boursières exposées à la vue, mais elles doivent être mappées sur les propriétés natives du viewmodel auquel elles seront liées.Cela nécessite un "nettoyage" qui pourrait être nécessaire lors du transfert des données vers le modèle/la vue.

Ainsi, la vue ne connaît que le modèle de vue. Cela signifie également que si le modèle n'était pas hérité, il pourrait être implémenté en tant qu'interface et réduire davantage le couplage entre le modèle de vue.

1

Ma compréhension est que ViewModels sont aux modèles que les propriétés sont aux champs. C'est une analogie très lâche, mais cela implique que vous n'êtes pas correctement isolé si votre Vue accède directement à votre Modèle. Tout comme avec les propriétés triviales dans les champs privés enveloppant la classe, vous obtenez beaucoup de duplication et de code standard lors de l'encapsulation des propriétés de modèle pertinentes dans les propriétés ViewModel pour la consommation par la vue. C'est quelque chose qui me dérange avec ce modèle et je ne suis toujours pas décidé si les avantages valent le ballonnement.

Dans cet exemple particulier, je pense qu'il serait exagéré de créer une VM pour chaque instance StockQuote, car vous ne faites probablement pas de logique significative pour la vue qui représente un StockQuote individuel. Je pense que c'est beaucoup plus propre et plus facile à maintenir dans ces petits cas de se lier directement à la classe Model directement. Créer une VM pour le petit cas réduirait le couplage, mais cela augmenterait aussi la complexité et je pense que c'est un jugement au cas par cas pour savoir si cela est bénéfique.

Questions connexes