Наследование контекстного меню в WPF - PullRequest
2 голосов
/ 22 ноября 2011

У меня есть 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 Ответ

3 голосов
/ 22 ноября 2011

Вы можете объявить элементы как ресурсы и ссылаться на них:

<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>

(* x:Shared важно)


Другой возможностью было бы создание MenuItems с помощью подхода объектной модели, вы просто привязываете ItemsSource к некоторому списку объектов, которые моделируют функциональность MenuItem (т.е. свойства для дочерних элементов, заголовка икоманда), то вы можете создать одну Remove модель, которая может быть частью нескольких списков.

...