Pregunta

Quiero construir una aplicación simple con el patrón MVVM.

Esta aplicación tendrá dos partes principales:

  • menú en la parte superior
  • contenido a continuación

La navegación será simple:

  • cada elemento de menú (por ejemplo, "Gestionar clientes" o "Ver informes") llenará el área de contenido con una nueva página que tiene alguna funcionalidad particular

He hecho esto antes con el código detrás donde el controlador de eventos de código subyacente para los elementos del menú tenía todas las páginas cargadas y la que debería mostrarse se cargó como elemento secundario de un StackPanel. Sin embargo, esto no funcionará en MVVM, ya que no desea llenar manualmente un StackPanel sino mostrar, por ejemplo, un '' ítem de página '' objeto con un DataTemplate, etc.

Entonces, aquellos de ustedes que han creado una simple aplicación de menú de clic como esta con MVVM, ¿cuál era su estructura básica de aplicación? Estoy pensando en estas líneas:

MainView.xaml:

<DockPanel LastChildFill="False">

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

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

</DockPanel>

donde el Menú se llena con una colección de "Artículos de página" y el DataTemplate muestra el Título de cada " objeto PageItem " como el encabezado de cada elemento de menú.

Y el ContentControl se llenará con un par View / ViewModel que tiene una funcionalidad completa, pero no estoy seguro de eso.

¿Fue útil?

Solución

Primero, creo que deberías mantener el controlador de eventos de código subyacente, no tiene sentido cambiar un controlador de eventos simple de 2 líneas a un monstruo complejo dirigido por comandos sin ninguna razón práctica (y no digas comprobabilidad, este es el principal menú, se probará cada vez que ejecute la aplicación).

Ahora, si desea ir a la ruta MVVM pura, todo lo que tiene que hacer para que su menú active un comando, primero, en alguna sección de recursos agregue este estilo:

<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>

Este estilo hará que el elemento del menú active el SwitchViewCommand en el modelo de vista adjunto con el DataContext de MenuItem como parámetro de comando.

La vista real es la misma que su código con una referencia adicional a ese estilo como ItemContainerStyle (por lo que se aplica al elemento de menú y no al contenido de DataTemplate):

<DockPanel LastChildFill="False">

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

Ahora en el modelo de vista que necesita (usé cadenas porque no tengo su código 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; }

Y use cualquier clase de comando que use para hacer que el comando llame a este código:

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

Ahora, cuando el usuario hace clic en un elemento del menú, el elemento del menú llamará al SwitchViewCommand con el elemento de la página como parámetro.

El comando llamará a DoSwitchViewCommand que establecerá la propiedad SelectedPageItem

La propiedad generará NotifyPropertyChanged que hará que la UI se actualice a través del enlace de datos.

O bien, puede escribir un controlador de eventos de 2 líneas, su elección

Otros consejos

podría imaginar una colección ObservableCollection en la máquina virtual, que contiene todas las páginas que se pueden llamar desde el menú. A continuación, vincule un ItemControl y el ContentControl para que ContentControl siempre muestre el CurrentItem de esa Lista. Por supuesto, el menú solo se unirá a alguna propiedad de Título  mientras que ContentControl adoptará todo el elemento y conectará una vista apropiada según el tipo.

Otra opción es usar un ListBox en lugar de un menú, diseñar el ListBox para que parezca un menú y luego puede enlazar al valor seleccionado, así:

<DockPanel LastChildFill="False">

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

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

</DockPanel>

Tenga en cuenta IsSynchronizedWithCurrentItem = " True " para establecer el elemento seleccionado y el {Binding PageItemsMainMenu /} con la barra inclinada final para usarlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top