WPF – Как заставить команду переоценить «CanExecute» через свой CommandBindings

У меня есть Menu котором каждый элемент MenuItem в иерархии имеет свойство Command установленное в RoutedCommand я определил. CanExecute CommandBinding обеспечивает обратный вызов для оценки CanExecute который управляет включенным состоянием каждого MenuItem .

Это почти работает. Первоначально элементы меню вызывают правильные состояния включения и выключения. Однако, когда данные, которые CanExecute обратный вызов CanExecute используют изменения, мне нужна команда для повторного запроса результата из моего обратного вызова, чтобы это новое состояние отражалось в пользовательском интерфейсе.

По-видимому, для этого не существуют общедоступные методы RoutedCommand или CommandBinding .

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

Не самый красивый в книге, но вы можете использовать CommandManager, чтобы аннулировать все команды:

 CommandManager.InvalidateRequerySuggested(); 

Подробнее о MSDN

Для тех, кто сталкивается с этим позже; Если вы используете MVVM и Prism, то реализация функции ICommand в .RaiseCanExecuteChanged() DelegateCommand Prism предоставляет метод .RaiseCanExecuteChanged() для этого.

Я не мог использовать CommandManager.InvalidateRequerySuggested(); потому что я получал удар производительности.

Я использовал команду делегирования MVVM Helper , которая выглядит как ниже (я немного изменил ее для нашего req). вам нужно вызвать command.RaiseCanExecuteChanged() из VM

 public event EventHandler CanExecuteChanged { add { _internalCanExecuteChanged += value; CommandManager.RequerySuggested += value; } remove { _internalCanExecuteChanged -= value; CommandManager.RequerySuggested -= value; } } ///  /// This method can be used to raise the CanExecuteChanged handler. /// This will force WPF to re-query the status of this command directly. ///  public void RaiseCanExecuteChanged() { if (canExecute != null) OnCanExecuteChanged(); } ///  /// This method is used to walk the delegate chain and well WPF that /// our command execution status has changed. ///  protected virtual void OnCanExecuteChanged() { EventHandler eCanExecuteChanged = _internalCanExecuteChanged; if (eCanExecuteChanged != null) eCanExecuteChanged(this, EventArgs.Empty); } 

Если вы применили свой собственный class, который реализует ICommand вы можете потерять много автоматических обновлений статуса, заставляя вас полагаться на ручное обновление более чем необходимо. Он также может разорвать InvalidateRequerySuggested() . Проблема в том, что простая реализация ICommand не связывает новую команду с CommandManager .

Решение состоит в том, чтобы использовать следующее:

  public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); } 

Таким образом, подписчики подключаются к CommandManager а не к вашему classу, и могут нормально участвовать в изменениях состояния команды.

Я реализовал решение для обработки зависимости свойств от команд, здесь ссылка https://stackoverflow.com/a/30394333/1716620

благодаря этому вы получите команду вроде этого:

 this.SaveCommand = new MyDelegateCommand(this, //execute () => { Console.Write("EXECUTED"); }, //can execute () => { Console.Write("Checking Validity"); return PropertyX!=null && PropertyY!=null && PropertyY.Length < 5; }, //properties to watch (p) => new { p.PropertyX, p.PropertyY } ); 
  • WPF: имя не существует в пространстве имен
  • Как связать несколько значений с одним текстовым блоком WPF?
  • Как установить ViewModel в окне в XAML с использованием свойства DataContext?
  • Что делает звезда WPF (Width = "100 *")
  • Страница vs Окно в WPF?
  • Как использовать FolderBrowserDialog из приложения WPF
  • Связывающие элементыСвойства ComboBoxColumn в WPF DataGrid
  • c # - подход для сохранения пользовательских настроек в приложении WPF?
  • Конвертер связыванияПараметр
  • Есть ли хороший способ конвертировать между BitmapSource и Bitmap?
  • WPF ListView отключает выбор
  • Давайте будем гением компьютера.