Pergunta

Eu quero construir uma aplicação simples com o padrão MVVM.

Esta aplicação terá duas partes principais:

  • Menu em cima
  • conteúdo abaixo

A navegação será simples:

  • cada item de menu (por exemplo, "Gerir Clientes" ou "Ver relatórios") será preencher a área de conteúdo com uma nova página que tem alguma funcionalidade específica

Eu tenho feito isso antes com código por trás , onde o código-behind manipulador de eventos para itens de menu tinha todas as páginas carregadas e o que deve ser exibido foi carregado como um filho de um StackPanel. Isso, no entanto, não funcionará no MVVM desde que você não quer ser preenchendo manualmente um StackPanel mas exibindo por exemplo um objeto "PageItem" com um DataTemplate, etc.

Assim, aqueles de vocês que fizeram uma aplicação simples-menu do botão como este com MVVM, qual foi sua estrutura básica aplicativo eu estou pensando ao longo destas linhas:?

MainView.xaml:

<DockPanel LastChildFill="False">

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

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

</DockPanel>

onde o menu é preenchido com uma coleção de "PageItems" e os DataTemplate exibe o título de cada um "objeto PageItem" como o cabeçalho de cada MenuItem.

E o ContentControl será preenchido com um par Ver / ViewModel que tem funcionalidade completa, mas não tenho certeza sobre isso.

Foi útil?

Solução

Primeiro, eu acho que você deve manter o código-behind manipulador de eventos, não há nenhum ponto na mudança de um simples manipulador de eventos de 2 linhas a um monstro de comando complexa impulsionado por nenhuma razão prática (e não digo testebility, esta é a principal menu, ele será testado cada vez que você executar o aplicativo).

Agora, se você quiser ir a rota MVVM puro, tudo o que você tem que fazê-lo para fazer o seu fogo menu de um comando, em primeiro lugar, em alguma seção de recursos adicionar esse 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 vai fazer o fogo item de menu um a SwitchViewCommand sobre o modelo de vista anexado com DataContext do MenuItem como o parâmetro de comando.

A visão real é o mesmo que o seu código com uma referência adicional a esse estilo como o ItemContainerStyle (por isso se aplica ao item de menu e não o conteúdo do DataTemplate):

<DockPanel LastChildFill="False">

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

Agora no modelo de vista que você precisa (eu usei cordas, porque eu não tenho o 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; }

e usar qualquer classe de comando que você usar para fazer o comando chamar esse código:

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

Agora, quando o usuário clica em um item de menu o item de menu irá chamar o SwitchViewCommand com o item de página como parâmetro.

O comando chamará o DoSwitchViewCommand que irá definir a propriedade SelectedPageItem

A propriedade irá aumentar o NotifyPropertyChanged que vai fazer a atualização UI via ligação de dados.

Ou, você pode escrever um manipulador de eventos de 2 linhas, a sua escolha

Outras dicas

Eu poderia imaginar um ObservableCollection no VM, que contém todas as páginas a ser exigível a partir do menu. Em seguida, vincular um ItemsControl E o ContentControl a ele para fazer a ContentControl sempre mostrar o CurrentItem a partir dessa lista. Claro, o menu só irá ligar-se a alguma propriedade Título enquanto o ContentControl adotará todo o item ea ficha de alguma visão apropriada de acordo com o tipo.

Outra opção é usar uma caixa de listagem em vez de um menu, o estilo de caixa de listagem para se parecer com um menu e, em seguida, você pode ligar para o valor selecionado, como este:

<DockPanel LastChildFill="False">

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

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

</DockPanel>

Observe o IsSynchronizedWithCurrentItem = "True" para definir o item selecionado eo {Binding PageItemsMainMenu /} com a barra no final de usá-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top