首页 > 解决方案 > 主顶部菜单和右键单击上下文菜单之间的 WPF 共享菜单

问题描述

我正在尝试在我的应用程序顶部菜单栏上的某些内容和 WPF 界面中某些内容的右键单击上下文菜单之间创建一个共享菜单。我已经用谷歌搜索了 aroudn,但我不知道如何只分享 menuitems 列表。

这是帮助描述它的 UI 图片:

在此处输入图像描述

它的工作方式是当列表中的一个项目(如背景所示)被选中时,该菜单就可以使用了。我想这样做,以便当您右键单击列表中的项目时,它也显示相同的菜单。我想避免重复代码,所以我在窗口资源中为 MenuItem 定义了一个资源:

<MenuItem x:Key="modUtilsMenu">
    <MenuItem Header="{Binding SelectedMod.ModName}" IsEnabled="False" FontWeight="Bold" />
    <MenuItem Header="{DynamicResource string_Checkforupdates}" Command="{Binding SelectedModCheckForUpdatesCommand}" ToolTip="{DynamicResource string_tooltip_checksForUpdatesToThisMod}" >
        <MenuItem.Icon>
            <fa:ImageAwesome Style="{StaticResource EnableDisableImageStyle}" Icon="Cloud" Foreground="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Height="16" Width="16"/>
        </MenuItem.Icon>
    </MenuItem>
    <MenuItem Header="{DynamicResource string_RestoremodfromME3Tweaks}" Command="{Binding RestoreModFromME3TweaksCommand}" ToolTip="{DynamicResource string_tooltip_forcesUpdateCheck}" >
        <MenuItem.Icon>
            <fa:ImageAwesome Style="{StaticResource EnableDisableImageStyle}" Icon="CloudDownload" Foreground="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Height="16" Width="16" RenderOptions.BitmapScalingMode="HighQuality"/>
        </MenuItem.Icon>
    </MenuItem>
    ...

然后我将它作为 Mod Utils 菜单项的子元素添加到界面中:

<MenuItem Header="{DynamicResource string_ModUtils}" Padding="4" IsEnabled="{Binding SelectedMod,  Converter={StaticResource NullEnabledConverter}}">
     <StaticResource ResourceKey="modUtilsMenu"/>
</MenuItem>

显然这不起作用,因为它在资源中定义了第二个 MenuItem。

在此处输入图像描述

但是,我不确定如何存储菜单项的“列表”以添加为另一个对象的子项,因为 MenuItem 和 ContextMenu 的根容器元素不一样。这些都是基于命令的菜单项。我也会在上下文菜单中遇到同样的问题 - 我如何只共享内容而不共享容器?我必须进行数据绑定吗?

我已经查看了如何在 WPF 中的上下文菜单和常规菜单之间共享菜单定义,但这似乎仅适用于单个菜单项。我想我可以为他们每个人都这样做,但我正在寻找是否有一种方法可以做到这一点,我只需要在一个地方而不是三个地方更新它就可以让它工作。

标签: c#wpfmenu

解决方案


Menu并且ContextMenu都是 type ItemsControl。您可以像这样对待它们,例如绑定到项目模型的集合并指定一个DataTemplate.

下面的示例创建一个MenuItemXAML 资源的集合。
要允许集合的多个实例,将x:Shared属性设置为 很重要False。否则,无论引用的数量如何,菜单都将仅在可视树的一个位置呈现:

<Window>
  <Window.Resources>
    <x:Array x:Key="SharedMenuItems" 
             Type="MenuItem" 
             x:Shared="False">
      <MenuItem Header="File">
        <MenuItem Header="Save" />
      </MenuItem>
      <MenuItem Header="Settings" />
    </x:Array>
  </Window.Resources>

  <StackPanel x:Name="RootPanel" viewModels:Item.IsMarkedAsRead="True">
    <Menu ItemsSource="{StaticResource SharedMenuItems}" />

    <Grid>
      <Grid.ContextMenu>
        <ContextMenu ItemsSource="{StaticResource SharedMenuItems}" />
      </Grid.ContextMenu>

    </Grid>
  </StackPanel>
</Window>

推荐阅读