WPF:空时隐藏ContextMenu

时间:2010-11-16 09:13:21

标签: wpf mvvm contextmenu

我有一个上下文菜单,通过数据绑定获取菜单项(我使用的是MVVM模式):

<ContextMenu ItemsSource="{Binding Path=ContextMenuItems}" />

这很好用。但是,在没有要显示的菜单项的情况下,我不希望上下文菜单显示。有没有办法实现这个目标?某种XAML触发器可能吗?

当没有孩子时,我尝试捕捉Opened事件,关闭上下文菜单。这有效,但上下文菜单仍然闪烁......

6 个答案:

答案 0 :(得分:22)

您可以定义隐式样式:

<Style TargetType="{x:Type ContextMenu}">
    <Style.Triggers>
        <Trigger Property="HasItems" Value="False">
            <Setter Property="Visibility" Value="Collapsed" />
        </Trigger>
    </Style.Triggers>
</Style>

这应该适用于所有上下文菜单。

答案 1 :(得分:15)

可能绑定到菜单项集合计数属性并使用转换器设置上下文菜单的可见性。

 <ContextMenu ItemsSource="{Binding Path=ContextMenuItems}"
              Visibility="{Binding Path=ContextMenuItems.Count,Converter={StaticResource zeroToHiddenConverter}}">

public  class ZeroToHiddenConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    {
        int count = (int) value;

        if (count == 0) 
        {
            return Visibility.Hidden;
        }
        else
        {
            return Visibility.Visible;
        }
    }

答案 2 :(得分:3)

下面是如何为隐藏空上下文菜单设置应用程序范围的样式。

HasItems是ContextMenu本身的依赖属性,因此您可以根据该布尔值设置上下文菜单的可见性。

以下是如何在资源字典中执行此操作:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <BooleanToVisibilityConverter x:Key="VisibilityOfBool" />

    <Style TargetType="{x:Type ContextMenu}">
        <Setter Property="Visibility" Value="{Binding HasItems, RelativeSource={RelativeSource Self}, Converter={StaticResource VisibilityOfBool}}"/>
    </Style>
</ResourceDictionary>

答案 3 :(得分:1)

如果您在TreeView控件(可能还有任何列表类型控件)上使用Tendlon的解决方案并带有上下文菜单,则会出现问题。

  1. 右键单击没有上下文菜单项的节点=&gt;没有任何事情发生(这很好)
  2. 左键单击具有上下文菜单项的节点=&gt;出现上下文菜单(不好)

答案 4 :(得分:0)

您可以尝试使用值转换器对Items.Count上的Visibility进行绑定 - 这会阻止您的菜单出现:)

答案 5 :(得分:0)

我想出了一个使用OnContextMenuOpening回调的TreeView解决方案。它可以防止Alex G提到的问题。如果您使用XAML样式折叠菜单,那么当contextmenu为空时它不会出现,但是当您左键单击另一个项目时它会出现。

代码查找想要打开ContextMenu的TreeViewItem,如果没有项目,则将事件的Handled属性设置为true。

protected override void OnContextMenuOpening(ContextMenuEventArgs e) {
     var item = FindTreeViewItem(e.OriginalSource as DependencyObject);
     var contextMenu = item.ContextMenu;
     if (contextMenu != null && !contextMenu.HasItems) {
         e.Handled = true;
     }
 }

 private TreeViewItem FindTreeViewItem(DependencyObject dependencyObject) {
     if (dependencyObject == null) {
         return null;
     }
     var treeViewItem = dependencyObject as TreeViewItem;
     if (treeViewItem != null) {
         return treeViewItem;
     }
     return FindTreeViewItem(VisualTreeHelper.GetParent(dependencyObject));
}