主顶部菜单和右键单击上下文菜单之间的 WPF 共享菜单

WPF shared menu between main top menu and right click context menu

我正在尝试在我的应用程序顶部菜单栏上的某些内容与 WPF 界面中某些内容的右键单击上下文菜单之间创建一个共享菜单。我已经在 google 上搜索了,但我无法弄清楚如何只共享菜单项列表。

这里有一张 UI 的图片来帮助描述它:

它的工作方式是当列表中的一个项目(如背景所示)被选中时,这个菜单就可以使用了。我想这样做,当您右键单击列表中的一个项目时,它也会显示相同的菜单。我想避免重复代码,所以我在 window 资源中为 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。

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

我看过 How do I share a menu definition between a context menu and a regular menu in WPF,但那似乎只适用于单个菜单项。我想我可以为他们中的每一个都做,但我想看看是否有一种方法可以做到这一点,我只需要在一个地方而不是三个地方更新它就可以让它工作。

MenuContextMenu 都是 ItemsControl 类型。你可以像这样对待他们,例如绑定到项目模型的集合并指定 DataTemplate.

以下示例将 MenuItem 的集合创建为 XAML 资源。
要允许集合的多个实例,将 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>