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.