MVVM中构建显示各种页面的菜单的最佳方法是什么?

Edw*_*uay 8 wpf mvvm application-design

我想用MVVM模式构建一个简单的应用程序.

该应用程序将包含两个主要部分:

  • 菜单在上面
  • 内容如下

导航很简单:

  • 每个菜单项(例如"管理客户"或"查看报告")将使用具有某些特定功能的新页面填充内容区域

之前使用的代码已经完成了这一点,其中菜单项的代码隐藏事件处理程序已加载所有页面,应该显示的那个作为StackPanel的子项加载.但是,这在MVVM中不起作用,因为您不希望手动填充StackPanel,而是显示例如带有DataTemplate的"PageItem"对象等.

那些用MVVM制作了这样一个简单的点击菜单应用程序的人,你的基本应用程序结构是什么? 我正在考虑以下几点:

MainView.xaml:

<DockPanel LastChildFill="False">

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

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

</DockPanel>
Run Code Online (Sandbox Code Playgroud)

其中菜单填充了"PageItems"集合,DataTemplate将每个"PageItem对象"的标题显示为每个MenuItem的标题.

ContentControl将填充一个具有完整功能的View/ViewModel对,但我不确定.

Nir*_*Nir 9

首先,我认为你应该保留代码隐藏事件处理程序,没有任何意义将简单的2行事件处理程序更改为复杂的命令驱动的怪物没有任何实际原因(并且不说测试性,这是主菜单,它将在每次运行应用程序时进行测试).

现在,如果您确实想要使用纯MVVM路由,那么您必须执行此操作才能使菜单触发命令,首先,在某些资源部分添加此样式:

<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>
Run Code Online (Sandbox Code Playgroud)

此样式将使菜单项在附加的视图模型上触发SwitchViewCommand,并使用MenuItem的DataContext作为命令参数.

实际视图与您的代码相同,并且作为ItemContainerStyle对该样式的附加引用(因此它适用于菜单项而不是DataTemplate的内容):

<DockPanel LastChildFill="False">

    <Menu DockPanel.Dock="Top"
        ItemsSource="{Binding PageItemsMainMenu}" 
        ItemTemplate="{StaticResource MainMenuStyle}"
        ItemContainerStyle="{StaticResource MenuItemStyle}"/>
    <ContentControl 
    Content="{Binding SelectedPageItem}"/>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)

现在在您需要的视图模型中(我使用了字符串,因为我没有您的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; }
Run Code Online (Sandbox Code Playgroud)

并使用您使用的任何命令类来使命令调用此代码:

private void DoSwitchViewCommand(object parameter)
{
    SelectedPageItem = (string)parameter;
}
Run Code Online (Sandbox Code Playgroud)

现在,当用户单击菜单项时,菜单项将以页面项作为参数调用SwitchViewCommand.

该命令将调用将设置SelectedPageItem属性的DoSwitchViewCommand

该属性将引发NotifyPropertyChanged,它将通过数据绑定进行UI更新.

或者,您可以选择编写2行事件处理程序