2011-02-06 12 views
9

Sono nuovo di MVVM e ho deciso di andare avanti e iniziare ad adottarlo nei miei progetti futuri.Passaggio tra modalità di visualizzazione e modalità di modifica in MVVM?

Ho letto questa domanda e risposta correlate, ma non so come questo sarebbe stato implementato con MVVM.

Desidero che tutte le viste nel mio progetto abbiano 2 modalità, modalità di modifica e modalità di visualizzazione.
Non voglio che l'utente visualizzi di default TextBox per tutti i campi, preferisco che visualizzino TextBlocks (o imposti tutti i TextBoxe s come proprietà IsReadOnly su true (via lo stile ecc. Me lo dici ..)

Quando l'utente apre l'entità dovrebbe essere in genere TextBlocks, Labels (o readonly TextBoxes) ecc. E se fa clic su "Modifica" (se ha il permesso di farlo), dovrebbe andare in modalità Modifica, e tutto le etichette dei campi devono essere invertite in TextBoxes (RichTextBoxes ecc., ComboBoxes o altri campi modificabili che non sono solo etichette)

Sono sicuro che non sono l'unico ad avere questo problema, mi piacerebbe sentire dagli esperti qual è il modo più efficace per cambiare b tra queste modalità in puro MVVM e se sia comune dichiarare due viste separate per esso.

Si prega di fare riferimento a un buon articolo che spiega come farlo (forse è fatto da Visual Stato IDK).

UPDATE
io voglio sapere che cosa, piuttosto che come, la mia domanda riguarda il modello, ed è devo separare Edit Mode dalla modalità di visualizzazione sia a V o VM? Quindi, per favore, sottolinea questo dettaglio nella risposta.

Grazie in anticipo.

risposta

10

utilizzare la proprietà IsReadOnly per le caselle di testo e si legano che alla "modalità di modifica" proprietà:

<TextBox .... IsReadOnly={Binding IsViewMode} ... /> 

Poi, nel tuo modello di vista:

public bool IsViewMode 
{ 
    get { return _IsViewMode; } 
    set 
    { 
     _IsViewMode= value; 
     // Call NotifyPropertyChanged when the source property is updated. 
     NotifyPropertyChanged("IsViewMode"); 
    } 
} 

IsViewMode default true e viene commutato a false quando l'utente fa clic su "modifica". La rilegatura renderà immediatamente modificabili tutte le caselle di testo.

Si potrebbe fare lo stesso per gli altri controlli, anche se in questi casi sarà la proprietà IsEnabled in grado di eseguire il binding, anche se i controlli saranno disattivati.

di scambiare blocchi di testo e i controlli avrete bisogno di avere entrambi i controlli che condividono la stessa posizione in una griglia e la loro visibilità controllati dalla struttura IsViewMode tramite una coppia di convertitori:

<TextBlock Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=DirectConverter} ... /> 
<ComboBox Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=InvertedConverter} ... /> 

La diretta convertitore è:

return IsViewMode ? Visibility.Visible : Visibility.Collapsed; 

Il convertitore invertito è:

return IsViewMode ? Visibility.Collapsed : Visibility.Visible; 
+0

E gli altri campi? Ho detto che volevo che alcuni campi si invertissero in un DropDown, alcuni in uno slider, alcuni in un raccoglitore di date, mentre nel modo di visualizzazione sono tutti semplici TextBlocks/etichette? E questa è una parte molto essenziale per me. – Shimmy

+0

@Shimmy - scusa, mi sono perso quel pezzettino (non so perché). Puoi fare lo stesso per i ComboBox, ma potrebbe essere la proprietà 'IsEnabled' che devi associare. – ChrisF

+0

Quindi stai dicendo che dovrei creare una vista comune per le modalità di modifica/visualizzazione, avendo tutti i controlli dichiarati uno vicino all'altro impostando il controllo IsReadOnly o Visibility su IsViewMode sulla VM (usando il convertitore BooleanToVisibility per i controlli da nascondere), è giusto? ** Ho aggiunto del contenuto alla mia domanda. ** – Shimmy

2

Viewmodel: manterrei sicuramente un solo viewmodel con una proprietà ViewMode come descritto nella risposta di ChrisF. ViewModels separati sarebbero semplicemente poco eleganti.

Visualizza: Come vedo, hai almeno tre opzioni, con vari pro e contro.

  1. Solo in sola lettura di tutti i controlli, come suggerito nella risposta di ChrisF. Pro: la cosa più semplice da fare Contro: Questa è una brutta UI a mio modesto parere.

  2. Crea display seaparate e modifica i controlli in contenitori separati. Associare la visibilità dei contenitori a ViewMode. Pro: Un'esperienza utente più piacevole può essere offerta qui. Puoi persino animare le transizioni da una all'altra. Contro: raddoppia il numero di controlli (potrebbe danneggiare le prestazioni per finestre molto grandi). Posizionare i controlli all'interno dei due contenitori esattamente nelle stesse posizioni dei pixel può diventare un po 'non banale in un fluido ui.

  3. Per ogni controllo di modifica in xaml, posizionare un controllo del display sopra di esso. Associare la visibilità alla proprietà ViewMode. Pro: nessuna duplicazione dei controlli delle etichette, quindi leggermente più veloce. Contro: È più difficile ottenere materiale di animazione e altri aggiustamenti di visualizzazione.

Modifica: in base ai chiarimenti forniti, ho scelto di sostituire la risposta precedente in quanto praticamente si occupava principalmente del come e non del cosa.

+0

Ho aggiunto del contenuto alla mia domanda. Non lo dichiarerei così. Odio che ViewModel sappia che esiste un'enumerazione Visibility ... Seguirò [risposta di ChrisF] (http://stackoverflow.com/questions/4917047/switching-between-view-mode-and-edit-mode-in -mvvm/4917104 # 4917104) utilizzando convertitori BooleanToVisibilit/BooleanFlagSwitch ecc. Ho appena ricevuto la risposta che la modalità di visualizzazione e la modalità di modifica NON dovrebbero essere separate comunque. – Shimmy

+0

@Shimmy: Penso che mentre la modalità Display e Edit dovrebbe appartenere alla stessa classe di vista e legata allo stesso viewmodel, i controlli per essi dovrebbero essere separati per una migliore esperienza dell'interfaccia utente. Ho cambiato la risposta per riflettere lo stesso. – anshul

+1

Non c'è assolutamente nulla di sbagliato nel modello di visualizzazione sapendo che esiste una cosa come la visibilità. –

3

Ci penso in questo modo: la vista è ciò che sembra e il ViewModel è il modo in cui interagisce con l'utente. Poiché un'interfaccia readonly ha un comportamento sostanzialmente diverso rispetto a un'interfaccia di lettura/scrittura, allora ci dovrebbero essere due diversi ViewModels.

Ora ho creato un edit ViewModel che ha ereditato da un display ViewModel perché ho considerato la funzionalità di modifica come un'estensione della funzionalità di visualizzazione. Questo funziona per semplici applicazioni di tipo CRUD in cui l'utente sta direttamente modificando i campi senza molta logica aziendale.

D'altra parte, se si ha un processo aziendale più complesso (o flusso di lavoro) che si sta modellando, in genere il modo in cui si manipolano le informazioni è molto diverso dal modo in cui si desidera visualizzarlo. Pertanto, in genere separerei i due ViewModel a meno che non fosse solo CRUD.

+0

Esattamente, sto parlando di CRUD Come ho detto, sono nuovo di MVVM e voglio impararlo. Puoi riferirmi a un buon articolo su come implementare un'applicazione CRUD in modo MVVM? Il mio problema sono anche le transizioni tra le diverse visualizzazioni – Shimmy

+0

Esattamente, sto parlando di CRUD Come ho detto, sono nuovo di MVVM e voglio impararlo. Puoi riferirmi a un buon articolo su come implementare un'applicazione CRUD in modo MVVM? ** La mia principale il problema sono anche le transizioni tra le diverse viste.** – Shimmy

+1

@Shimmy - Suggerisco [MVVM avanzato] (http://joshsmithonwpf.wordpress.com/advanced-mvvm/) di Josh Smith. È breve, ma molto informativo e puoi ottenere il codice sorgente. –

3

La risposta di ChrisF va bene se si desidera seguire la rotta IsReadOnly. Se si desidera passare al percorso TextBlock-to-TextBox, tuttavia, il modo più efficiente è disporre di un controllo che commuta il modello, tramite trigger, in base al valore di una proprietà IsInEditMode o IsInViewModel.

2

In primo luogo, mi piacerebbe implementare una classe base astratta per i miei modelli di visualizzazione che hanno implementato IEditableObject e esposti comandi appropriati per BeginEdit, EndEdit e CancelEdit. Potrebbe essere che le implementazioni effettive per quei tre metodi dovrebbero essere fino alle classi derivate, ma i comandi potrebbero vivere nella classe base.

In questo approccio, EndEdit aggiorna il modello con i valori correnti delle proprietà nel modello di vista.

Implementerei anche una proprietà booleana IsEditing nella classe base, per l'utilizzo in trigger di dati, in modo che se voglio passare da una modalità all'altra senza (ad esempio) aprendo una finestra di dialogo modale, posso semplicemente farlo in uno stile .

Per quanto riguarda la progettazione visiva del front-end, trovo l'idea che una vista di sola lettura sia solo una vista di modifica con controlli di sola lettura che sia particolarmente adatta ai programmatori. In generale, se stai semplicemente presentando un oggetto a un utente, l'obiettivo di quella presentazione è fornire all'utente una rappresentazione informativa, chiara e intuitiva delle informazioni in quell'oggetto. Se stai permettendo all'utente di modificare un oggetto, l'obiettivo di quella presentazione è di rendere il compito di modificare tutte le proprietà modificabili dell'oggetto nel modo più semplice e chiaro possibile.

Questi sono due insiemi di obiettivi molto diversi. Ad esempio, mentre il sesso, l'altezza e il peso di una persona potrebbero essere importanti informazioni da raccogliere per un'applicazione, probabilmente non è così importante per il sistema presentare tali informazioni all'utente nella maggior parte dei contesti. Sembra una cosa molto naturale da fare se quello che hai in testa è che la modalità di modifica è proprio come la modalità di visualizzazione. Ma se stai ponendo le esigenze dell'utente, e non il programmatore, davanti e al centro, potrebbe non essere la cosa giusta da fare.

Problemi correlati