2010-04-14 17 views
10

Il punto di M-V-VM, come tutti sappiamo, riguarda la sperarazione delle preoccupazioni. In modelli come MVVM, MVC o MVP, lo scopo principale è disaccoppiare la vista dai dati, creando in tal modo componenti più flessibili. Dimostrerò per prima cosa uno scenario molto comune trovato in molte app WPF e quindi farò il mio punto:M-V-VM, il modello non sta filtrando nella vista?

Supponiamo di avere qualche applicazione StockQuote che trasmette un sacco di citazioni e le visualizza sullo schermo. In genere, devi avere questo:

StockQuote.cs: (Modello)

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

E poi avresti qualche tipo di servizio che alimenterebbe ObservableCollection con nuovi Stockquotes.

La mia domanda è questa: in questo tipo di scenario, lo stockquota è considerato il modello e lo stiamo esponendo alla vista attraverso ObservableCollection di ViewModel. Che in pratica significa, la nostra vista ha conoscenza del modello. Questo non viola l'intero paradigma di M-V-VM? O mi manchi qualcosa qui ....?

risposta

3

No. Non stai esponendo StockQuote. Si sta specificando solo un'interfaccia (scarsamente tipizzata) nella vista. La vista conosce solo due proprietà: Simbolo e Prezzo. Puoi facilmente sostituire StockQuote con qualsiasi altra cosa purché li implementa.

+0

Questo è un buon punto, anche se si basa sulla natura "libera" di WPF Data Binding. Se avessi scritto un test unitario per la VM che faceva affidamento sulla collezione StockQuote, tuttavia, si interromperà se hai cambiato la classe StockQuote. –

8

Sono più familiare con MVC che MVVM, ma è generalmente accettato che la Vista abbia conoscenza del Modello. Finché il Modello non ha conoscenza della vista, questo è ok.

Se questa è davvero una preoccupazione per qualsiasi motivo, controlla il disegno "Vista passiva", in cui la vista non conosce altro che i dati grezzi forniti.

+5

esattamente quello che stavo per digitare. La vista deve sapere * qualcosa * sul modello, altrimenti di cosa si tratta? – timdev

7

In MVVM il modello di vista è una via di mezzo tra la vista e il modello che espone i dati dal modello in un modo che può essere gestito facilmente dalla vista. In un'applicazione MVVM rigida, la vista non conosce il modello, ma solo il modello di visualizzazione.

Nel tuo esempio concreto il modello di vista non dovrebbe essere chiamato StockQuoteViewModel ma StockQuotesViewModel (essere consapevoli del plurale), perché il modello di vista sta esponendo molte quotazioni da una specifica collezione ui che è facile da gestire per la vista (perché ObservableCollection<T> strumenti INotifyCollectionChanged<T>). Il tipo di elementi nella raccolta deve essere un modello di visualizzazione (ad esempio StockQuoteViewModel) che espone i dati da un singolo oggetto StockQuote. In tale modello di visualizzazione è possibile aggiungere logica come l'aggiunta di un simbolo $ a Price e così via.

È spesso più semplice esporre alcuni oggetti del modello in un modello di vista, ma il modo corretto sarebbe creare un modello di vista per ogni classe del modello.

migliori saluti,
Oliver Hanappi

0

Forse ho sbagliato, ma questo non è l'idea del ViewModel per incapsulare completamente il modello. Ad esempio, le quotazioni azionarie sono esposte alla vista, ma devono essere mappate alle proprietà native del modellabile a cui verrebbero quindi associate.Questo è necessario per "pulire" che potrebbe essere necessario durante il trasferimento dei dati al modello/vista.

In questo modo la vista conosce solo il modello di visualizzazione. Significa anche che se il modello non era legacy potrebbe essere implementato come un'interfaccia e ridurre ulteriormente l'accoppiamento tra il viewmodel.

1

La mia comprensione è che ViewModels sono per i modelli come le proprietà sono ai campi. Questa è un'analogia molto sciolta, ma implica che tu non sia adeguatamente isolato se View sta accedendo direttamente al tuo Modello. Proprio come con le proprietà banali in una classe che avvolge i campi privati, si finisce con un sacco di duplicati e codice boilerplate quando si avvolgono le proprietà del modello rilevanti nelle proprietà ViewModel per il consumo da parte della vista. Questo è qualcosa che mi infastidisce con questo modello e non sono ancora deciso se i benefici valgano la pena.

In questo particolare esempio, penso che sarebbe eccessivo creare una VM per ogni istanza di StockQuote, poiché probabilmente non si sta facendo alcuna logica significativa per la Vista che rappresenta un singolo StockQuote. Penso che sia molto più pulito e più manutenibile in questi piccoli casi per legare semplicemente direttamente alla classe Model. La creazione di una VM per il caso di piccole dimensioni ridurrebbe l'accoppiamento, ma aumenterebbe anche la complessità e penso che sia un giudizio caso per caso sul fatto che questo sia utile.

Problemi correlati