Наследование контекстного меню в WPF
У меня есть 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>
Контекстное меню определяется так
<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>
Другое контекстное меню также должно содержать такие общие элементы, как удалить. Они должны реплицироваться копировальной пастой каждый раз, когда изменяются свойства команды и т. Д. Ад для ремонтопригодности. Есть ли способ определить контекстное меню, которое содержит общие элементы, а затем "извлечь" определенные контекстные меню?
Изменить: я нашел решение с подсказками из этой темы: я определяю коллекцию с общими элементами и использую составную коллекцию при определении меню, чтобы включить как новые элементы, так и коллекцию общих элементов
<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>
1 ответ
Вы можете объявить элементы как ресурсы и ссылаться на них:
<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>
(Thex:Shared
это важно)
Другая возможность будет генерировать MenuItems
с помощью подхода объектной модели, вы просто связываете ItemsSource
к некоторому списку объектов, которые моделируют функциональность MenuItem
(т.е. свойства для дочерних элементов, заголовка и команды), затем вы можете создать один Remove
модель, которая может быть частью нескольких списков.