CanExecute Logic for DelegateCommand

更新:焦点变成MVVM而不是实际的问题所以我正在更新它。

我遇到了CanExecute for DelegateCommand的问题。 在我调用RaiseCanExecuteChanged之前它没有更新,这是否是所需的行为?

在此处输入图像描述

我在这里上传了一个简单的示例项目来重现这个问题: http : //dl.dropbox.com/u/39657172/DelegateCommandProblem.zip

问题是这个,我有两个像这样的Buttons 。 一个是绑定Command到一个RelayCommand实现,另一个是绑定到DelegateCommand的Prism实现

 

ViewModel ICommands

 DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate); RelaySaveCommand = new RelayCommand(param => Save(), param => CanSaveRelay); 

CanExecute方法/谓词

 public bool CanSaveDelegate() { return HasChanges; } public bool CanSaveRelay { get { return HasChanges; } } 

两者都使用属性HasChanges 。 更新HasChanges ,只更新CanSaveRelay 。 这是它的意思吗?

正如已经提到的那样,这是DelagateCommand预期行为,而不是bug。 DelegateCommand不会自动引发CanExecuteChanged事件,您必须在适当时通过调用RaiseCanExecuteChanged手动引发该事件。 而RelayCommandCommandManager.RequerySuggested事件中继。 每次用户点击某个位置或按下按钮时都会引发此事件。

对于不方便或没有适当的地方调用RaiseCanExecuteChanged (就像在你的场景中你必须在模型上订阅PropertyChanged事件等)我创建了以下简单的包装器,以确保CanExecute方法的在CommandManager.RequerySuggested事件上自动执行wrapped命令:

 public class AutoCanExecuteCommandWrapper : ICommand { public ICommand WrappedCommand { get; private set; } public AutoCanExecuteCommandWrapper(ICommand wrappedCommand) { if (wrappedCommand == null) { throw new ArgumentNullException("wrappedCommand"); } WrappedCommand = wrappedCommand; } public void Execute(object parameter) { WrappedCommand.Execute(parameter); } public bool CanExecute(object parameter) { return WrappedCommand.CanExecute(parameter); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } } 

你可以像这样使用它:

 DelegateSaveCommand = new AutoCanExecuteCommandWrapper(new DelegateCommand(Save, CanSaveDelegate)); 

Prism提供的DelegateCommand中存在一个错误,它不会引发CanExecute事件。 我把头撞到墙上一天,直到我进入Prism框架提供的DelegateCommand类。 我没有代码,但我可以稍微发布我的分辨率。

另一种方法是使用其他RelayCommand框架之一。

编辑
而不是重新发布代码,还有其他提出解决方案的SO问题:

  • WPF-Prism CanExecute方法未被调用

肯特B.有一篇好文章: MVVM基础设施:DelegateCommand