2014-04-04 10 views
6

Nel mio View ho tre oggetti, di cui uno è visibile in qualsiasi momento. Nel mio Model ho un'enumerazione per rappresentare i tre stati.Miglior approccio per impostare la visibilità in MVVM

Come devo implementare il mio ViewModel?

a) Creare un valore booleano per la visibilità di ciascun oggetto e associare ogni oggetto a questo (con un convertitore bool-> visibilità).

b) Legarsi all'enum, con un convertitore univoco per ciascun oggetto.

c) Legarsi all'enumerazione, con un singolo convertitore che accetta un parametro.

d) Utilizzare un gestore dello stato visivo con fotogrammi chiave booleani e guidare lo stato dalla VM con una proprietà associata.

e) Associare l'enumerazione VM dal codice sottostante e impostare la visibilità attraverso il codice.

f)?

Sto seriamente sperando che la risposta sia f) (ovvero la scelta ovvia che mi sfugge), perché non sono veramente felice con a) attraverso e).

Pensieri benvenuti e apprezzati.

+0

puoi mostrare qualche codice dal tuo modello e viewmodel per vedere il tuo enum e l'uso nel tuo vm – blindmeis

+0

btw se la tua vista vuole solo un oggetto alla volta perché il tuo viewmodel non ha esporre un oggetto alla volta? – blindmeis

risposta

3

L'approccio Best in MVVM non significa necessariamente facile. Mi piacciono i seguenti approcci:

a) Creare un valore booleano per la visibilità di ciascun oggetto e associare ogni oggetto a questo (con un convertitore bool-> visibilità).

Questo metodo è il più intuitivo e classico per impostare Visibilità per Control.

b) Legarsi all'enum, con un convertitore univoco per ciascun oggetto.

c) Legarsi all'enumerazione, con un singolo convertitore che accetta un parametro.

Nel caso del convertitore, Enum è il meglio non tenere in Model e nel lato di View. Perché il problema si risolve sul lato di View, che è abbastanza logico e qui per memorizzare la struttura dei dati. In linea di principio, non è critico.

Esempio:

public sealed class InvertableBooleanToVisibilityConverter : IValueConverter 
{ 
    enum Parameters 
    { 
     Normal, 
     Inverted 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var boolValue = (bool)value; 
     var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter); 

     if (direction == Parameters.Inverted) 
      return !boolValue ? Visibility.Visible : Visibility.Collapsed; 

     return boolValue ? Visibility.Visible : Visibility.Collapsed; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return DependencyProperty.UnsetValue; 
    } 
} 

Un paio di commenti su altri approcci:

d) utilizzare un gestore di stato visivo con fotogrammi chiave booleane, e guidare lo Stato da VM con una proprietà associata.

Per queste situazioni, sembra complicato, quindi non vedere il punto in esso. Tuttavia, se le condizioni di impostazione della visibilità non sono difficili, è possibile utilizzare VisualStateManager.

e) Associare il codice VM al codice sottostante e impostare la visibilità attraverso il codice.

Code-behind in questo caso non è giustificato quando è possibile risolvere il problema utilizzando gli strumenti tipici di MVVM (rilegatura, convertitori, ecc.). Credo che, in questo caso non sarebbe una violazione del principio di MVVM, se si sceglie l'elemento al Visibility non è la logica di business coinvolti, come ad esempio può venire impostazione di visibilità per pressione dei CheckBox, ToggleButton, ecc

+0

D'accordo, ho iniziato la codifica c) e mi sono fermato rapidamente quando ho realizzato che la mia vista (convertitore) faceva riferimento alla mia dichiarazione Enum dal modello. Mi piace l'approccio dello stato visivo concettualmente, e se uso l'opacità al posto dei fotogrammi chiave lo xaml non sarebbe troppo orribile. – 2stroke

+0

@ 2stroke: Tutto è possibile, se le condizioni non sono difficili, è possibile utilizzare 'VisualStateManager'. Forse lo aggiungerò alla mia risposta. –

0
c) Bind to the enum, with a single converter that takes a parameter. 

In questo modo ho risolto il problema con i pulsanti di opzione in cui è selezionato solo uno dei pulsanti di opzione. Sembra più difficile ma puoi riutilizzarlo più tardi e se ne hai l'idea è molto facile.

e) Bind to the VM enum from code behind, and set visibility thru code. 

Cattiva idea. Non è una buona pratica.

0

in aggiunta al mio commento. quando ho il compito di mostrare il contenuto diffrente in una vista a seconda di oggetti diversi. uso la maggior parte del tempo un contentcontrol e datatemplates.

<ContentControl Content="{Binding MyEnumObject}"/> 

ora nel mio ViewModel ho tutti gli oggetti differente tipi e impostare l'oggetto che voglio al mio legano proprietà alla vista.

private Blup _blup; //eg. is wanted when enum in model = 1 

    public object MyEnumObject {get;set;} 


    //set the content in your viewmodel 
    this.MyEnumObject = _blup; 

ora basta un DataTemplate per visualizzare i vostri oggetti

<DataTemplate DataType="{x:Type local:Blup}"> 
    <view:MyBlupViewControl/> 
    </DataTemplate> 

ma forse io m totalmente sbagliato. ma la tua domanda concreta lascia tanto spazio all'interpretazione

+0

Questa potrebbe essere la risposta che sto cercando .... Sono ancora nuovo a WPF. Nel mio caso i 3 elementi dell'interfaccia utente che desidero passare sono solo 3 diverse etichette con contenuto, formattazione, colori, ecc. Così nel tuo esempio dovrei creare tre tipi nella mia VM e creare un DataTemplate per ognuno in XAML con la formattazione necessaria? – 2stroke

+0

questo è quello che faccio :) – blindmeis

Problemi correlati