Как получить отключенный элемент меню WPF верхнего уровня, когда все его дочерние элементы отключены? - PullRequest
4 голосов
/ 13 мая 2011

У меня есть следующий MenuItem внутри контекстного меню в моем приложении WPF:

<MenuItem Header="Email">
      <MenuItem Command="Commands:CommandRepository.GenerateUserEmailCommand"
                CommandParameter="{Binding Path=SelectedItems}"
                Header="Email User">
      </MenuItem>
      <MenuItem Command="Commands:CommandRepository.GenerateManagerEmailCommand"
                    CommandParameter="{Binding Path=SelectedItems}"
                    Header="Email Manager">
      </MenuItem>
</MenuItem>

Проблема заключается в том, что когда обе команды электронной почты возвращают CanExecute = false, и поэтому обе команды отключаются,Элемент меню верхнего уровня «Электронная почта» остается включенным.Я знаю, что мог бы связать IsEnabled элемента верхнего меню со свойством Children, а затем использовать конвертер, чтобы решить, когда его следует отключить, но, похоже, это должно происходить автоматически.Разве это не весь смысл использования CommandBindings (то есть они заботятся о IsEnabled для вас)?Есть ли лучший способ сделать это?

Ответы [ 3 ]

1 голос
/ 13 мая 2011

Я могу придумать два способа сделать это:

1) Если вы не возражаете против кода позади (я стараюсь избегать его с WPF), вы можете просто создать обработчик событий для IsEnabledChanged, который проверяет, было ли для свойства IsEnabled установлено значение false. Если бы это было так, вы могли бы сделать что-то вроде

ParentMenuItem.IsEnabled = ParentMenuItem.Items.Count( c => c is MenuItem && (c as MenuItem).IsEnabled == true) > 0

2) Создайте ViewModel для типов Родительского MenuItem и Дочернего MenuItem и привяжите параметр Enabled родительского Представления MenuItem к свойству IsEnabled модели представления. Модель представления вернула бы false, используя аналогичный

this.Children.Count(c => c.IsEnabled == true) > 0
1 голос
/ 19 октября 2011

Определите команду RootMenu, затем добавьте ее в корневое меню

Header="Email" Command="Commands:CommandRepository.RootMenu" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=.}"   

Привязать команду к следующему RootMenuCanExecute

    public static void DropDownMenuCanExecute(object sender, CanExecuteRoutedEventArgs e) {
        e.CanExecute = false;
        ItemsControl parent = e.Parameter as ItemsControl;
        if (parent.Items.Count == 0) { return; }
        foreach (var i in parent.Items) {
            ICommandSource cs = i as ICommandSource; if (cs==null) { continue; }
            if (cs.Command == null) { continue; }
            if (cs.Command.CanExecute(cs.CommandParameter)) { e.CanExecute = true; return; }
        }
    }

это довольно дорого, но работает. Берегись, чтобы не было слишком много детей MenuItem

1 голос
/ 13 мая 2011

почему ваш «Email» MenuItem должен быть отключен? только потому что дети такие?

Я думаю, что ваш подход к использованию мультисвязи и конвертера - это хороший способ сделать то, что ВЫ хотите.

...