WPF TreeViewItem 上下文菜单取消突出显示项
Posted
技术标签:
【中文标题】WPF TreeViewItem 上下文菜单取消突出显示项【英文标题】:WPF TreeViewItem Context Menu Unhighlights Item 【发布时间】:2011-03-03 02:21:37 【问题描述】:一段时间以来,我一直遇到这个问题,并提出了一些不太理想的解决方案。问题是当 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】:WPF 的默认行为是在 ContextMenu 打开时将 TreeViewItem 更改为灰色,但与 WPF 中的几乎所有其他内容一样,您可以覆盖它:
-
创建附加属性 ContextMenuOpened
在 TreeViewItem 样式中,将 ContextMenuOpened 绑定到“ContextMenu.IsOpen”
添加一个触发器,当 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 相结合,调用更改前景色和背景色的触发器,以使项目仍显示为选中状态。
【讨论】:
太棒了。我自己永远不会想到这一点。不过有一件事:背景设置不正确,但前景设置正确。我感觉它与无法编译的 TargetName="Bd" 有关。 我的回答假设您的自定义 TreeViewItem ControlTemplate 是默认 TreeViewItem ControlTemplate 的编辑副本。 “Bd”是边框的默认 TreeViewItem ControlTemplate 中使用的名称。如果为 TreeViewItem 构建了一个完全自定义的 ControlTemplate 而不是复制系统并编辑它,您的模板中可能根本没有边框,或者它可能被命名为不同的东西。在这种情况下,您可能需要不同的 TargetName 来设置项目的背景颜色。 我刚刚意识到我可能假设太多:也许您根本没有为 TreeViewItem 创建自定义 ControlTemplate。在那种情况下,除了替换资源之外,我看不到任何影响模板内边框颜色的方法,正如您所指出的,它具有某种全局范围。因此,我认为您将需要使用自定义 ControlTemplate。在 Blend 中,只需右键单击控件并从上下文菜单中选择 Edit Template -> Edit A Copy,然后将我的 MultiTrigger 添加到模板中触发器列表的底部。 好吧,希望它不会变成那样,但它必须这样做(不幸的是,我没有 Blend,但我之前找到了默认模板)。再次感谢。 嘿,我怎样才能通过 C# 而不是通过 XAML 来实现这一点,因为我已经通过 .cs 文件创建了树视图控件。以上是关于WPF TreeViewItem 上下文菜单取消突出显示项的主要内容,如果未能解决你的问题,请参考以下文章
wpf treeview中动态创建的treeViewItem如何用右键触发菜单?
如何在 wpf 中的 treeviewitem 中访问 treeviewitem?
禁用WPF TreeView(或TreeViewItem)选择?
C# WPF TreeViewItem MouseDoubleClick 事件在 TreeViewItem 与 TreeViewItem.Header
WPF 如果选中它,则只保留一个 TreeViewItem 展开,折叠其他的,除非它是 Selected TreeViewItem 的祖先