WPF-как заставить команду повторно оценить 'CanExecute' через его CommandBindings
у меня есть Menu каждая MenuItem в иерархии есть свои Command свойство установлено в RoutedCommand Я определил. Связанный CommandBinding обеспечивает обратный вызов для оценки CanExecute который управляет включенным состоянием каждого MenuItem.
этой почти строительство. Пункты меню изначально приходят с правильными включенными и отключенными состояниями. Однако, когда данные, что мой CanExecute обратный вызов использует изменения, мне нужна команда для повторного запроса результата мой обратный вызов для того, чтобы это новое состояние было отражено в пользовательском интерфейсе.
там, кажется, нет никаких публичных методов на RoutedCommand или CommandBinding для этого.
обратите внимание, что обратный вызов используется снова, когда я нажимаю или набираю элемент управления (я предполагаю, что он запускается при вводе, потому что наведение мыши не вызывает обновления).
5 ответов:
Не самый красивый в книге, но вы можете использовать CommandManager для аннулирования всех commandbinding:
CommandManager.InvalidateRequerySuggested();Посмотреть подробнее на сайте MSDN
для тех, кто сталкивается с этим позже; если вы случайно используете MVVM и Prism, то Prism's
DelegateCommandреализацияICommandпредоставляет.RaiseCanExecuteChanged()метод для этого.
Я не мог использовать
CommandManager.InvalidateRequerySuggested();потому что я получил удар по производительности.я использовал MVVM Helperделегирует команду, которая выглядит как ниже (я немного подправил ее для нашего req). вы должны позвонить
command.RaiseCanExecuteChanged()от VMpublic event EventHandler CanExecuteChanged { add { _internalCanExecuteChanged += value; CommandManager.RequerySuggested += value; } remove { _internalCanExecuteChanged -= value; CommandManager.RequerySuggested -= value; } } /// <summary> /// This method can be used to raise the CanExecuteChanged handler. /// This will force WPF to re-query the status of this command directly. /// </summary> public void RaiseCanExecuteChanged() { if (canExecute != null) OnCanExecuteChanged(); } /// <summary> /// This method is used to walk the delegate chain and well WPF that /// our command execution status has changed. /// </summary> protected virtual void OnCanExecuteChanged() { EventHandler eCanExecuteChanged = _internalCanExecuteChanged; if (eCanExecuteChanged != null) eCanExecuteChanged(this, EventArgs.Empty); }
если вы свернули свой собственный класс, который реализует
ICommandвы можете потерять много автоматических обновлений статуса заставляя вас полагаться на ручное обновление больше, чем должно быть необходимо. Он также может сломатьсяInvalidateRequerySuggested(). Проблема в том, что простойICommandреализация не может связать новую команду сCommandManager.решение состоит в том, чтобы использовать следующее:
public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); }таким образом подписчики присоединяются к
CommandManagerа не ваш класс и может должным образом участвовать в изменении статуса команды.
я реализовал решение для обработки зависимости свойств от команд, здесь Ссылка https://stackoverflow.com/a/30394333/1716620
благодаря этому у вас будет такая команда:
this.SaveCommand = new MyDelegateCommand<MyViewModel>(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 } );