WPF 中的上下文菜单继承

Pet*_*pov 4 wpf maintainability xaml contextmenu

我有 TreeView,其中包含不同的项目类型。项目样式是通过自定义 ItemContainerStyleSelector 属性定义的。

我的样式都共享一个基本样式,并且每种样式中只定义了特定于项目的内容。它看起来像这样:

<Style x:Key="BaseStyle" TargetType="{x:Type TreeViewItem}">
...
</Style>

<Style x:Key ="SomeSpecificStyle" TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource BaseStyle}">
   <Setter Property="ContextMenu" Value="{StaticResource NodeContextMenu}"/>
   ...  
</Style>

<Style x:Key ="SomeSpecificStyle" TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource BaseStyle}">
   <Setter Property="ContextMenu" Value="{StaticResource AnotherNodeContextMenu}"/>
   ...  
</Style>
Run Code Online (Sandbox Code Playgroud)

上下文菜单定义如下

<ContextMenu x:Key="NodeContextMenu">
  <MenuItem Header="Select Views" Command="{Binding Path=OpenViewsCommand}" />
  ...other specific entries
  <MenuItem Header="Remove" Command="{Binding Path=DocumentRemoveCommand}" />
  ...other entries common for all menus
</ContextMenu>
Run Code Online (Sandbox Code Playgroud)

另一个上下文菜单还应该包含那些常见的项目,例如删除。每次命令属性等发生更改时,都需要通过复制粘贴来复制这些内容。可维护性简直就是地狱。有没有办法定义一个包含常用项目的上下文菜单,然后“派生”特定的上下文菜单?

编辑:我找到了一个带有此线程提示的解决方案:我定义一个包含常见项目的集合,并在定义菜单时使用复合集合以包含新项目和常见项目集合

<CompositeCollection x:Key="CommonItems"> 
  <MenuItem Header="Remove" Command="{Binding Path=DocumentRemoveCommand}">
  ....Other common stuff
</CompositeCollection>

<ContextMenu x:Key="NodeContextMenu">
  <ContextMenu.ItemsSource>
    <CompositeCollection>
      <MenuItem Header="Select Views" Command="{Binding Path=OpenViewsCommand}" />
      <CollectionContainer Collection="{StaticResource CommonItems}" />
    </CompositeCollection>
  </ContextMenu.ItemsSource>
</ContextMenu>
Run Code Online (Sandbox Code Playgroud)

H.B*_*.B. 5

您可以将这些项目声明为资源并引用它们:

<Some.Resources>
    <MenuItem x:Key="mi_SelectViews" x:Shared="false"
              Header="Select Views" Command="{Binding Path=OpenViewsCommand}" />
    <MenuItem x:Key="mi_Remove" x:Shared="false"
              Header="Remove" Command="{Binding Path=DocumentRemoveCommand}" />
</Some.Resources>
Run Code Online (Sandbox Code Playgroud)
<ContextMenu x:Key="NodeContextMenu">
  <StaticResource ResourceKey="mi_SelectViews" />
  ...other specific entries
  <StaticResource ResourceKey="mi_Remove" />
  ...other entries common for all menus
</ContextMenu>
Run Code Online (Sandbox Code Playgroud)

(这x:Shared很重要)


MenuItems另一种可能性是通过对象模型方法生成,您只需将 绑定ItemsSource到一些对 a 的功能进行建模的对象列表MenuItem(即子项、标题和命令的属性),然后您可以创建一个Remove模型,该模型可以是多个列表。