I have TreeView which contains different item types. Item Styles are defined over a custom ItemContainerStyleSelector property.
My styles are all sharing a base style and only item specific stuff is defined in each style. It looks like this:
<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>
The context menu is defined like this
<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>
Another context menu also should contain those common items like remove. These need to be replicated by copy paste every time the command properties, etc are changing. A hell for maintainability. Is there a way to define a context menu which contains the common items, and then "derive" specific context menus?
Edit: I found a solution with the hints from this thread: I define a Collection with the common items, and use a composite collection when defining a menu to include both new items and the common items collection
<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>
                You can declare the items as resource and reference them:
<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>
<ContextMenu x:Key="NodeContextMenu">
  <StaticResource ResourceKey="mi_SelectViews" />
  ...other specific entries
  <StaticResource ResourceKey="mi_Remove" />
  ...other entries common for all menus
</ContextMenu>
(The x:Shared is important)
Another possibility would be to generate MenuItems via a object model approach, you just bind the ItemsSource to some list of objects which model the functionality of a MenuItem (i.e. properties for child items, header and command), then you can create one Remove model which can be part of multiple lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With