WPF自定义ICommand实现和CanExecuteChanged事件

时间:2010-09-22 10:22:58

标签: wpf binding icommand

在我的WPF UI中,我通过以下代码使用我在xaml中引用的RoutedCommands:

Command="viewModel:MessageListViewModel.DeleteMessagesCommand"

我不喜欢这个到我的ViewModel类的静态链接,我认为这不如创建自定义ICommand实现那么好,并使用如下语法

Command="{Binding DeleteMessagesCommand}"

创建一个之后,我注意到我所做的一个主要缺点:RoutedCommands使用CommandManager并且(以某种方式对我来说完全不透明)触发CommandManager.RequerySuggested事件,以便自动重新获取它们的CanExecute方法。至于我的自定义实现,CanExecute只在启动时触发一次,之后再也不会再触发。

有人为此提供了优雅的解决方案吗?

2 个答案:

答案 0 :(得分:8)

按如下方式实施CanExecuteChanged事件:

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

将命令分配给控件时,它会订阅CanExecuteChanged事件。如果您将其“重定向”到CommandManager.RequerySuggested事件,则会在CommandManager.RequerySuggested被触发时通知控件。

答案 1 :(得分:0)

我非常喜欢Prism的DelegateCommand实现用于viewmodel绑定(http://msdn.microsoft.com/en-us/library/ff654132.aspx)。您可以通过调用RaiseCanExecuteChanged在每个命令调用者上调用CanExecute()。

简单用法示例:

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}"