更新:焦点变成了MVVM而不是实际的问题所以我正在更新它。
我对CanExecute
DelegateCommand
遇到问题。在我致电RaiseCanExecuteChanged
之前它没有更新,这是否是理想的行为?
我上传了一个简单的示例项目,在这里重现了这个问题:http://dl.dropbox.com/u/39657172/DelegateCommandProblem.zip
问题是,我有两个Buttons
这样的。一个是将Command
绑定到RelayCommand
实现,另一个绑定到DelegateCommand
的Prism实现
<Button Command="{Binding DelegateSaveCommand}"/>
<Button Command="{Binding RelaySaveCommand}"/>
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
次更新。这是它的意思吗?
答案 0 :(得分:21)
正如已经提到过的,这是DelagateCommand
的预期行为,而不是错误。
DelegateCommand
不会自动提升CanExecuteChanged
事件,您必须在适当时调用RaiseCanExecuteChanged
手动提升该事件。而RelayCommand
传递CommandManager.RequerySuggested
事件。每次用户单击某个位置或按下按钮时,都会引发此事件。
对于不方便或没有适当的地方来调用RaiseCanExecuteChanged
的情况(就像在你的场景中你必须在模型上订阅PropertyChanged
事件等)我创建了遵循简单的包装器,确保在CanExecute
事件上自动执行包装命令的CommandManager.RequerySuggested
方法:
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));
答案 1 :(得分:0)
Prism提供的DelegateCommand中存在一个错误,它不会引发CanExecute事件。我把头撞到墙上一天,直到我进入Prism框架提供的DelegateCommand
课程。我没有代码,但我可以稍微发布我的决议。
另一种方法是使用其他一个RelayCommand框架。
修改强>
而不是重新发布代码,还有其他提出解决方案的SO问题:
肯特B.有一篇好文章:MVVM Infrastructure: DelegateCommand
答案 2 :(得分:0)
如果您想坚持使用DelegateCommand
,可以使用ObservesCanExecute
:
DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate).ObservesCanExecute(CanSaveDelegate);
请注意,如果您正在使用属性执行CanExecute检查,那么ObservesProperty
也可用。但是随后您的媒体资源必须调用NotifyPropertyChanged。