2010-07-15 11 views
13

Ho una vista che visualizza uno DataGrid che è associato a un ObservableCollection nel ViewModel. Per motivi di discussione, supponiamo di avere una vista Team contenente un team DataGrid, in cui ogni riga rappresenta uno Player.Multiple ViewModelli associati a una singola vista

La mia domanda riguarda il tipo di dati che dovrei usare per rappresentare i giocatori nella mia collezione Team. È una buona idea che gli oggetti della collezione siano ViewModels stessi? In questo caso, la mia vista Team sarà associata a un singolo Team ViewModel ea qualsiasi numero di Player ViewModels (nella raccolta Team).

La presenza di più ViewModels associati a una singola vista viola le linee guida di progettazione per MVVM e esiste un modo preferito per implementare questo scenario?

Grazie!

risposta

28

No va bene; ogni oggetto dovrebbe essere un ViewModel a sé stante. Rende il codice più pulito, interazioni migliori e ricorda che, se funziona bene, è corretto (anche se viola le linee guida).

Lo farei esattamente come si prescrive. Legherei la mia rete a uno Team, che avrebbe uno ObservableCollection<Player>, dove Player è un'altra classe di tipo ViewModel. Ogni articolo di riga otterrebbe il Player come DataContext e quindi sei ancora vincolante per le proprietà ViewModel come ti aspetteresti: e Player può ancora avere public proprietà per ICommand s (probabilmente RelayCommands) per la manipolazione!

Spero che questo aiuti!

+5

+1 per "se funziona bene, è corretto (anche se viola le linee guida)" – andyp

+0

No scherzo. +1 anche da me. –

+1

Ho ricevuto un lol da "se funziona è corretto", ma ho visto un sacco di cose che funzionano e sono così lontane da corrette che mi fanno venir voglia di scagliare. :) – CindyH

9

Lontano da violare le linee guida, penso che questo sia il design consigliato. Almeno nei miei progetti vedrete questo schema ripetutamente.

Questo modello è particolarmente utile in combinazione con DataTemplates. Ad esempio si potrebbe definire un DataTemplate nella vostra Application.Resources per le vostre PlayerViewModel in questo modo:

<DataTemplate DataType="viewModels:PlayerViewModel"> 
    <StackPanel Orientation="Vertical"> 
     <Image Source="/Images/Player.png"/> 
     <TextBlock Text="{Binding Name}"/> 
    </StackPanel> 
</DataTemplate> 

E poi se si vuole visualizzare un elenco di giocatori che semplicemente associa un ListBox ecc per il vostro TeamViewModel.Players ObservableCollection e si ottenere automaticamente il DataTemplate sopra indicato per ogni giocatore:

<ListBox ItemsSource="{Binding Players}"/> 
2

sono d'accordo con entrambe le altre risposte (quelle di Kieren e Groky), ma sento che non riescono a parlare di una considerazione molto importante in questa decisione.

È necessario creare un modello di vista solo se c'è qualcosa di specifico della vista su ciò che si sta facendo. Se tutto ciò che si sta facendo è vincolante per i dati e si invocano comandi che naturalmente appartengono al modello, non c'è motivo di creare un modello di visualizzazione.

Ad esempio, si supponga:

  1. vostro lettore ha una proprietà Name, una proprietà Rank, un metodo di promuovere(), ed un metodo Delete().
  2. La tua vista è una semplice che ti permette di modificare il Nome e il Grado di qualsiasi giocatore, e ha anche pulsanti per promuovere ed eliminare i giocatori.

In questo caso l'aggiunta di un modello di vista tra la vista e il modello è inutile. Una tale visione può legarsi direttamente al modello:

  • Bind TextBox.Text alla proprietà Name
  • Bind Slider.Value alla proprietà Rango
  • Bind sul pulsante Alza al metodo promuovere()
  • Associare il pulsante Elimina per il metodo Delete()

Nota che, invece di legare il pulsante Elimina per il metodo delete() si può decidere di impostare il suo comando per ApplicationCommands.Delete e utilizzare un CommandBinding per richiamare il Metodo Delete().

Il mio punto qui è che nella maggior parte dei casi se i modelli sono ben progettati non sarà necessario inserire un oggetto modello di vista. Un modello di visualizzazione è davvero necessario solo quando è necessario tenere traccia dello stato specifico della vista (come "Player corrente"), le conversioni sono troppo complesse per essere gestite da un semplice binding oppure sono necessari comandi che influenzano diversi oggetti del modello e/o vista proprietà del modello allo stesso tempo.

Secondo la mia esperienza, se il modello è progettato correttamente, solo circa il 50% circa di tutte le visualizzazioni richiede effettivamente un modello di visualizzazione e nel caso di elementi in un elenco questo è più simile al 20%.

Un esempio di tempo in cui è possibile utilizzare un modello di visualizzazione per un elemento in un elenco è quando è necessario mantenere un flag "selezionato" separato che fa parte della vista ma non del modello e della funzionalità di base in ListBox non è abbastanza.

+0

Citazione: "Tale visualizzazione può essere associata direttamente al modello: Associare TextBox.Text alla proprietà Name Bind Slider.Value alla proprietà Rank Associare il pulsante Promuovi al metodo Promote()" Da quando fa un Il modello ha un metodo? Associare il pulsante Elimina al metodo Delete() – Elisabeth

+0

Praticamente tutti i modelli hanno metodi. Un modello senza metodi sarebbe come una persona senza muscoli. Senza metodi, come diresti alla modella di fare qualcosa? Sostituiresti 'person.Clap()' con 'person.Clap = true' o' PersonOperations.Clap (person) '? Ognuno di questi sembra alquanto imbarazzante. Prima della programmazione orientata agli oggetti c'era una programmazione strutturata, in cui si poteva creare una funzione 'PersonClap (Person * person)', ma IMHO il modo orientato agli oggetti di esprimere le cose è molto più pulito. –

+0

L'unica situazione in cui un oggetto modello non avrebbe metodi è se non potrebbe mai * fare * qualsiasi cosa, ma era solo un record di dati non elaborati. Tali oggetti sono piuttosto rari nelle applicazioni reali. I possibili esempi potrebbero essere un punto dati raw ricevuto da un trasduttore o una voce bibliografica, ma anche questi potrebbero avere un metodo Delete(). –

Problemi correlati