Реализация пользовательской ICommand WPF и событие CanExecuteChanged - PullRequest
5 голосов
/ 22 сентября 2010

в моем интерфейсе WPF я использую RoutedCommands, на которые ссылаюсь в своем xaml через следующий код:

Command="viewModel:MessageListViewModel.DeleteMessagesCommand"

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

Command="{Binding DeleteMessagesCommand}"

Создав его, я замечаю один главный недостаток того, что я сделал: RoutedCommands используют CommandManager и (в некотором смыслесовершенно непрозрачно для меня) запустить событие CommandManager.RequerySuggested, чтобы их метод CanExecute запрашивался автоматически.Что касается моей пользовательской реализации, CanExecute запускается только один раз при запуске и больше никогда после этого.

У кого-нибудь есть изящное решение для этого?

Ответы [ 2 ]

8 голосов
/ 22 сентября 2010

Просто реализуйте событие CanExecuteChanged следующим образом:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

Когда вы назначаете команду для элемента управления, она подписывается на событие CanExecuteChanged.Если вы «перенаправите» его на событие CommandManager.RequerySuggested, элемент управления будет уведомляться при каждом срабатывании CommandManager.RequerySuggested.

0 голосов
/ 22 сентября 2010

Я очень предпочитаю реализацию Prism DelegateCommand для привязки viewmodel (http://msdn.microsoft.com/en-us/library/ff654132.aspx).. Вы можете вызывать CanExecute () при каждом вызове команды, вызывая для него RaiseCanExecuteChanged.

Простой пример использования:

public class ViewModel
{
   public ViewModel()
   {
      Command = new DelegateCommand<object>(x => CommandAction(), x => CanCommandAction());
   }

   bool state;

   public void ChangeState(bool value)
   {
      state = value;
      Command.RaiseCanExecuteChanged();
   }

   public DelegateCommand<object> Command {get; private set;}

   private void CommandAction()
   {
      //do smthn
   }

   private bool CanCommandAction() { return true == state; }
}

//and binding as usual
Command="{Binding Command}"
...