Domanda

Voglio creare una semplice applicazione con il modello MVVM.

Questa applicazione avrà due parti principali:

  • menu in alto
  • contenuto in basso

La navigazione sarà semplice:

  • ogni voce di menu (ad es. " Gestisci clienti " o " Visualizza report ") riempie l'area del contenuto con una nuova pagina che presenta alcune funzionalità particolari

Ho già fatto questo prima con il codice dietro dove il gestore di eventi code-behind per le voci di menu aveva tutte le pagine caricate e quella che doveva essere visualizzata veniva caricata come figlia di StackPanel. Questo, tuttavia, non funzionerà in MVVM poiché non si desidera riempire manualmente StackPanel ma visualizzare ad es. un " PageItem " oggetto con un DataTemplate, ecc.

Quindi quelli di voi che hanno realizzato una semplice applicazione di menu di scelta rapida come questa con MVVM, qual era la struttura di base dell'applicazione? Sto pensando in questo senso:

MainView.xaml:

<DockPanel LastChildFill="False">

    <Menu 
        ItemsSource="{Binding PageItemsMainMenu}" 
        ItemTemplate="{StaticResource MainMenuStyle}"/>

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

</DockPanel>

dove il menu è pieno di una raccolta di " PageItems " e DataTemplate visualizza il titolo di ciascun oggetto "PageItem" " come intestazione di ciascun MenuItem.

E ContentControl sarà riempito con una coppia View / ViewModel che ha funzionalità complete, ma non ne sono sicuro.

È stato utile?

Soluzione

In primo luogo, penso che dovresti mantenere il gestore di eventi code-behind, non ha senso cambiare un semplice gestore di eventi a 2 righe in un mostro complesso guidato da comandi senza motivo pratico (e non dire testabilità, questo è il principale menu, verrà testato ogni volta che esegui l'app).

Ora, se vuoi seguire la rotta MVVM pura, tutto ciò che devi fare per fare in modo che il tuo menu attivi un comando, prima, in alcune sezioni delle risorse aggiungi questo stile:

<Style x:Key="MenuItemStyle" TargetType="MenuItem">
    <Setter Property="Command" 
            Value="{Binding DataContext.SwitchViewCommand,
            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"/>
    <Setter Property="CommandParameter" 
            Value="{Binding}"/>
</Style>

Questo stile renderà la voce di menu un SwitchViewCommand sul modello di vista collegato con DataContext di MenuItem come parametro del comando.

La vista effettiva è la stessa del tuo codice con un riferimento aggiuntivo a quello stile di ItemContainerStyle (quindi si applica alla voce di menu e non al contenuto di DataTemplate):

<DockPanel LastChildFill="False">

    <Menu DockPanel.Dock="Top"
        ItemsSource="{Binding PageItemsMainMenu}" 
        ItemTemplate="{StaticResource MainMenuStyle}"
        ItemContainerStyle="{StaticResource MenuItemStyle}"/>
    <ContentControl 
    Content="{Binding SelectedPageItem}"/>
</DockPanel>

Ora nel modello di visualizzazione che ti serve (ho usato le stringhe perché non ho il tuo codice PageItem):

private string _selectedViewItem;
public List<string> PageItemsMainMenu { get; set; }
public string SelectedPageItem
{
    get { return _selectedViewItem; }
    set { _selectedViewItem = value; OnNotifyPropertyChanged("SelectedPageItem"); }
}
public ICommand SwitchViewCommand { get; set; }

E usa qualunque classe di comando usi per fare in modo che il comando chiami questo codice:

private void DoSwitchViewCommand(object parameter)
{
    SelectedPageItem = (string)parameter;
}

Ora, quando l'utente fa clic su una voce di menu, la voce di menu chiamerà SwitchViewCommand con la voce di pagina come parametro.

Il comando chiamerà DoSwitchViewCommand che imposterà la proprietà SelectedPageItem

La proprietà genererà NotifyPropertyChanged che renderà l'aggiornamento dell'interfaccia utente tramite l'associazione dei dati.

Oppure puoi scrivere un gestore di eventi a 2 righe, a tua scelta

Altri suggerimenti

Potrei immaginare un ObservableCollection nella VM, che contiene tutte le pagine per essere richiamabili dal menu. Quindi associare un ItemsControl e ContentControl ad esso per fare in modo che ContentControl mostri sempre CurrentItem da quell'elenco. Naturalmente, il menu si legherà solo ad alcune proprietà del titolo  mentre ContentControl adotterà l'intero articolo e inserirà una vista appropriata in base al tipo.

Un'altra opzione è quella di utilizzare un ListBox invece di un menu, stile ListBox per assomigliare a un menu e quindi è possibile associare al valore selezionato, in questo modo:

<DockPanel LastChildFill="False">

    <ListBox 
        ItemsSource="{Binding PageItemsMainMenu}" 
        ItemTemplate="{StaticResource MainMenuStyle}"
        IsSynchronizedWithCurrentItem="True"/>

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

</DockPanel>

Nota IsSynchronizedWithCurrentItem = " True " per impostare l'elemento selezionato e {Binding PageItemsMainMenu /} con la barra finale per usarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top