WPF: скрытие ContextMenu, когда пусто - PullRequest
10 голосов
/ 16 ноября 2010

У меня есть контекстное меню, которое получает пункты меню через привязку данных (я использую шаблон MVVM):

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

Это отлично работает. Тем не менее, в тех случаях, когда нет пунктов меню для отображения, я не хочу, чтобы контекстное меню отображалось вообще. Есть ли способ сделать это? Может быть, какой-то триггер XAML?

Я пытался перехватить событие Opened или закрыть контекстное меню, когда нет дочерних элементов. Это работает, но контекстное меню все еще мигает ...

Ответы [ 6 ]

23 голосов
/ 21 февраля 2012

Вы можете определить неявный стиль:

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

Это должно работать сразу для всех ваших контекстных меню.

15 голосов
/ 16 ноября 2010

Может быть, привязать к вашему количеству элементов меню пунктов меню и использовать конвертер, чтобы установить видимость контекстного меню.

 <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;
        }
    }
3 голосов
/ 17 февраля 2012

Ниже описано, как можно настроить стиль приложения для скрытия пустых контекстных меню.

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>
1 голос
/ 17 октября 2011

Если вы используете решение Tendlon для элемента управления TreeView (и, возможно, любого элемента управления типа списка) с контекстным меню, у него есть проблемы.

  1. Щелкните правой кнопкой мыши узел без пунктов контекстного меню => Ничего не происходит (что хорошо)
  2. Щелкните левой кнопкой мыши узел с пунктами контекстного меню => Появится контекстное меню (что плохо)
0 голосов
/ 23 ноября 2016

Я придумал решение для TreeView, которое использует обратный вызов OnContextMenuOpening. Это предотвращает проблему, о которой говорил Алекс Г. Если вы свернете меню в стиле XAML, то оно не появится, когда контекстное меню пустое, однако впоследствии оно появится, когда вы щелкнете левой кнопкой мыши по другому элементу.

Код ищет TreeViewItem, который хочет открыть ContextMenu, и, если у него нет элементов, он устанавливает для свойства 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));
}
0 голосов
/ 16 ноября 2010

Вы можете попробовать сделать привязку к Visibility для Items.Count с помощью конвертера значений - это должно помешать появлению вашего меню:)

...