如何在 WPF 中为每个应用程序屏幕设置不同的菜单

How to have different menus for each application screen in WPF

我的应用程序有三个屏幕:Overview、CreateActivity 和 ViewActivities。

当我在 CreateActivity 中时,我想显示一些仅对该屏幕有意义的菜单,ViewActivities 屏幕也是如此,它将有另一个独占菜单。

这类似于现在 Microsoft Office 中发生的情况:您单击某个选项卡,菜单栏中会出现一些与该选项卡相关的额外菜单条目。

我应该如何在 WPF 中实现它?

目前,我的主要 window 如下所示。有一个 属性 ActiveScreen 类型 ViewModelBase,我想将菜单栏内容绑定到我的三个屏幕中的每一个。

<Window
        (...)
        x:Class="CompanyNamespace.Product.Views.ShellView">

    <Window.DataContext>
        <vm:ShellViewModel/>
    </Window.DataContext>

    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <!-- What here? -->
        </Menu>
        <ContentControl Content="{Binding ActiveScreen}"/>
    </DockPanel>

</Window>

我的建议是更改每个 Menu/MenuItem 的可见性。

首先创建一个带有 flags 属性的枚举。我可以添加一个项目 All = 7 但在这种情况下没有必要这样做。而是简单地从 XAML

中的 MenuItem 中删除 Visibility="..." 部分
[Flags]
public enum MenuSetTypes
{
    //I prefer adding a None in flags mode
    None = 0,

    //main items
    Overview = 1,
    CreateActivity = 2,
    ViewActivities = 4,

    //define multi state items
    OverviewAndCreate = 3,
    CreateAndView = 6,
}

添加可绑定的 属性 以查看模型

public MenuSetTypes MenuSetType { ... } 

菜单项XAML:

<MenuItem Header="SomeMenuVisibileInOverViewAndCreate"
          Visibility="{Binding ActiveScreen.MenuSetType,
          Converter={StaticResource MenuTypeToVisibilityConverter},
          ConverterParameter={x:Static enums:MenuSetTypes.OverviewAndCreate}}"/>

转换器代码:

public class MenuTypeToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //value & param highlights enum items that are in both value and param
        //so that by comparing it with None we can tell if there is any
        //overlapped enum item or not 
        return ((MenuSetTypes)value & (MenuSetTypes)parameter) == MenuSetTypes.None ?
             Visibility.Collapsed : Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}