WPF TreeViewItem Контекстное меню Элемент невыделенного - PullRequest
2 голосов
/ 13 июня 2010

У меня были проблемы с этим в течение некоторого времени, и я нашел несколько менее желательных решений. Проблема состоит в том, что когда контекстное меню TreeViewItem открыто, TreeViewItem неактивен. Возможно ли TreeViewItem оставаться выделенным, когда его ContextMenu открыто?

Проблема с затенением TreeViewItem заключается в том, что он не имеет отношения к контекстному меню и TreeViewItem и выглядит уродливо.

Обычно код, который я использую для настройки контекстного меню, таков. Иногда контекстное меню генерируется кодом с помощью PreviewRightMouseButtonDown EventSetter, но это не имеет значения:

    <TreeView>
        <TreeView.Resources>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem Header="Menu Item 1" />
                            <MenuItem Header="Menu Item 2" />
                        </ContextMenu>
                    </Setter.Value>
                </Setter>
            </Style>
        </TreeView.Resources>
        <TreeViewItem Header="Item 1">
            <TreeViewItem Header="Sub-Item 1"/>
        </TreeViewItem>
        <TreeViewItem Header="Item 2"></TreeViewItem>
    </TreeView>

Пока единственное решение, которое я нашел, это переопределить «серый» несфокусированный цвет с сфокусированным цветом, но тогда TreeView никогда не кажется несфокусированным, например, при нажатии другого элемента управления. У меня были проблемы с ListViews.

1 Ответ

2 голосов
/ 13 июня 2010

Поведение WPF по умолчанию при открытии ContextMenu меняет TreeViewItem на серый, но, как и практически все остальное в WPF, вы можете переопределить это:

  1. Создать вложенное свойство ContextMenuOpened
  2. В стиле TreeViewItem, связать ContextMenuOpened с "ContextMenu.IsOpen"
  3. Добавить триггер, который изменяет кисть, когда ContextMenuOpened и IsSelected имеют значение true

Вот прикрепленное свойство:

public class TreeViewCustomizer : DependencyObject
{
  public static bool GetContextMenuOpened(DependencyObject obj) { return (bool)obj.GetValue(ContextMenuOpenedProperty); }
  public static void SetContextMenuOpened(DependencyObject obj, bool value) { obj.SetValue(ContextMenuOpenedProperty, value); }
  public static readonly DependencyProperty ContextMenuOpenedProperty = DependencyProperty.RegisterAttached("ContextMenuOpened", typeof(bool), typeof(TreeViewCustomizer));
}

Вот сеттер в стиле:

<Setter Property="my:TreeViewCustomizer.ContextMenuOpened"
        Value="{Binding ContextMenu.IsOpen, RelativeSource={RelativeSource Self}}" />

Вот триггер:

<MultiTrigger>
  <MultiTrigger.Conditions>
    <Condition Property="IsSelected" Value="true"/>
    <Condition Property="my:TreeViewCustomizer.ContextMenuOpened" Value="true"/>
  </MultiTrigger.Conditions>
  <Setter TargetName="Bd"
          Property="Background"
          Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
  <Setter Property="Foreground"
          Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</MultiTrigger>

Как это работает: Каждый раз, когда ContextMenu открывается, устанавливается свойство IsOpen. Привязка приводит к тому, что ваше присоединенное свойство устанавливается в TreeViewItem. Это, в сочетании с IsSelected, вызывает триггер, который изменяет цвета переднего плана и фона, чтобы сделать элемент по-прежнему выделенным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...