2010-07-29 10 views
5

Questa domanda è un follow-up di this older una, ed è più una conferma che una domanda aperta.Aggiungere la modifica a MVVM in una struttura gerarchica di dati

La mia istanza ViewModel ha un'istanza privata del modello, _modelInst.
ViewModel ha accesso esclusivo ai dati del modello durante la modifica (quindi il modello non deve implementare INotifyPropertyChanged).

Ora ci sono tre modi mi è venuta come modificare i dati del modello dalla Vista:

  1. Ottenere/impostando direttamente nell'istanza modello
    esempio per semplici campi di valore
    return _modelInst.fieldname;
    _modelInst.fieldname = value;
    facile da implementare questo ...

  2. Creazione di un'istanza ViewModel e che operano sulla struttura dei dati del genitore
    esempio per tipi di oggetti più complessi, come le strutture:

    • Creazione di un nuovo ViewModel per quel tipo.
      ViewModel conosce il genitore e il suo nome di campo.
    • visualizzazione che in un ContentControl + DataTemplate
    • ricevendo/impostazione:
      tramite metodi del genitore con il nome del campo come parametro,
      sovrascrivendo l'intero oggetto originale anche se un solo campo viene modificato

    Ciò significa creare una nuova interfaccia (con routine di aggiornamento funzionanti su _modelInst), implementata dal genitore, per ciascuna di queste strutture.

  3. Creazione di istanze ViewModel con nessuna conoscenza diretta della struttura dei dati del genitore
    esempio per (liste di) Classi all'interno di classi genitore

    • Creazione di un nuovo ViewModel per ogni classe

    • Invio istruzioni per l'aggiornamento al genitore tramite comandi

      1. messaggi
      2. riflessione (genitore conosce quale figlio ha chiamato la funzione
        confrontando l'istanza a tutti i bambini memorizzati)

      Tutti questi sono un gran casino di attuazione, la creazione di funzioni per ogni campo del modello che è modificabile.
      Il che significa che praticamente tutti i campi del modello ...

(4.) Si potrebbe creare un ViewModel generico che funziona attraverso la riflessione da solo, in cui ogni sotto-oggetto conosce la sua madre e la sua nome campo (+ indice, se in una lista).
Solo la logica della radice interferirebbe con il modello.
Ma questa soluzione richiederebbe anche un mezzo per memorizzare il percorso in un campo entro _modelInst.

C'è qualche altro (più semplice) modo per raggiungere questo obiettivo?
Ho frainteso i principi di MVVM (di nuovo)?
MVVM è adatto alla manipolazione di strutture di dati gerarchiche di grandi dimensioni?

+0

Assumendo cliente come un oggetto modello, creano un CustomerViewModel che implementa oggetti ICommand per: RetrieveCustomer, createCustomer, UpdateCustomer, deleteCustomer (ognuno prendendo parametro di tipo Cliente). Quindi, la tua vista dovrebbe legarsi a questi oggetti ICommand e tu invii un CommandParameter di tipo Customer (molto probabilmente un binding da qualche parte nella tua vista). –

+0

Questo funziona bene su una struttura piatta, ad es. un elenco di clienti.Ma cosa succede se ho una gerarchia ad albero più complessa, come 'lista contatti' dove' contatto' è baseclass a 'business, cliente, privato' e' business' ha un 'lista ' ...? –

+0

Un ViewModel separato per ogni modello, sì? Per le classi derivate, potresti provare 'Business business = contatto come Business; if (business! = null) [fare cose relative a Business] ' –

risposta

0

Questa è un'ottima domanda per quale non ritengo ci sia una buona risposta che viene in magazzino con il modello MVC.

ViewModels funziona alla grande quando il modello a cui la mappa non ha figli.

Ma quando il modello ha figli, come in

clienti

 -->Order 

     -->Country 

(immaginando Paese fosse un oggetto figlio del Cliente) lo schema tipo di progettazione di rottura verso il basso.

La cosa migliore che ho trovato è utilizzare l'ereditarietà e esporre in modo selettivo solo quei bambini per i quali è necessaria la logica viewmodel. Altrimenti, accedi a le proprietà del modello della vista che arriveranno via ereditarietà.

public class CustomerView: // cliente ha ereditato da clienti (modello) {

public CustomerView(Customer customer) 
{ 
     this.FirstName = customer.FirstName 
     //etc.. 

     //Only if you need it, that is if you have some display-specific 
     //logic relating to country for a given view, you create 
     //a CountryView class that inherits from Country and gets populated 
     //by an instance of it as well 
     this.CountryView = new CountryView(customer.Country) 
} 

public CountryView CountryView {get;set;} //sadly you cannot override Country but you may be able to shadow it. 

public string DisplayColor 
{ 
    if(base.FirstName == "Joe") 
    { 
     return "red"; 
    } 
    return ""; 
} 

}

Questo diventa disordinato quando si tratta con i nipoti. Se qualcuno ha una soluzione migliore, mi piacerebbe sentirla.

Grazie