DelegateCommand 的 CanExecute 逻辑
更新:焦点变成了 MVVM 而不是实际问题,所以我正在更新它。
我在 DelegateCommand
的 CanExecute
方面遇到问题。在我调用 RaiseCanExecuteChanged 之前它不会更新,这是期望的行为吗?
我在这里上传了一个重现此问题的简单示例项目: http://dl.dropbox.com/u/39657172/DelegateCommandProblem.zip
问题是这样的,我有两个这样的 Button
。一种是将 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
。这就是事情本来的样子吗?
Update: The focus became MVVM instead of the actual question so I'm updating it.
I'm having a problem with CanExecute
for DelegateCommand
. It doesn't update before I call RaiseCanExecuteChanged
, is this the desired behavior?
I uploaded a simple sample project reproducing this problem here : http://dl.dropbox.com/u/39657172/DelegateCommandProblem.zip
The problem is this, I have two Buttons
like this. One is Binding Command
to a RelayCommand
implementation and the other is binding to the Prism implementation of DelegateCommand
<Button Command="{Binding DelegateSaveCommand}"/>
<Button Command="{Binding RelaySaveCommand}"/>
The ViewModel ICommands
DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate);
RelaySaveCommand = new RelayCommand(param => Save(), param => CanSaveRelay);
and the CanExecute
method/predicate
public bool CanSaveDelegate()
{
return HasChanges;
}
public bool CanSaveRelay
{
get { return HasChanges; }
}
Both are using the property HasChanges
. When HasChanges
is updated, only the CanSaveRelay
updates. Is this the way it's meant to be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如已经提到的,这是
DelagateCommand
的预期行为,而不是错误。DelegateCommand
不会自动引发CanExecuteChanged
事件,您必须在适当的时候通过调用RaiseCanExecuteChanged
手动引发该事件。而RelayCommand
则中继CommandManager.RequerySuggested
事件。每次用户单击某处或按下按钮时都会引发此事件。对于不太方便或没有合适的地方调用 RaiseCanExecuteChanged 的情况(例如在您的场景中,您必须订阅模型上的PropertyChanged 事件等)我创建了以下简单的包装器,确保在
CommandManager.RequerySuggested
事件上自动执行包装命令的CanExecute
方法:您可以像这样使用它:
As it already was mentioned, this is intended behavior of
DelagateCommand
, not a bug.DelegateCommand
doesn't raiseCanExecuteChanged
event automatically, you have to raise that event manually by callingRaiseCanExecuteChanged
when appropriate. WhereasRelayCommand
relays onCommandManager.RequerySuggested
event for that. This event is raised every time the user clicks somewhere or presses a button.For situations when it is not very convenient or there is no appropriate place for calling
RaiseCanExecuteChanged
(like in your scenario you have to subscribe toPropertyChanged
event on the model, etc) I have created the following simple wrapper that ensures that theCanExecute
method of the wrapped command is executed automatically onCommandManager.RequerySuggested
event:You can use it like this:
如果您想坚持使用
DelegateCommand
,您可以使用ObservesCanExecute
:请注意,如果您使用属性进行 CanExecute 检查,还可以使用
ObservesProperty
。但随后您的属性必须调用 NotifyPropertyChanged。If you want to stick to
DelegateCommand
you can useObservesCanExecute
:Note that there is also
ObservesProperty
available if you are using a property for your CanExecute check. But then your property has to call NotifyPropertyChanged.Prism 提供的 DelegateCommand 中存在一个错误,它不会引发 CanExecute 事件。我在墙上撞了一天,直到我深入了解 Prism 框架提供的
DelegateCommand
类。我没有代码,但我可以稍后发布我的解决方案。另一种方法是使用其他 RelayCommand 框架之一。
编辑
除了重新发布代码之外,还有其他提供解决方案的问题:
Kent B. 有一篇很好的文章:MVVM 基础设施:DelegateCommand
There is a bug in the DelegateCommand provided by Prism which doesn't raise the CanExecute event. I beat my head against the wall for a day until I dove into the
DelegateCommand
class provided by the Prism framework. I don't have the code with me, but I can post my resolution in a bit.The alternative is to use one of the other RelayCommand frameworks out there.
Edit
Rather than reposting the code, there are other SO questions that provide resolutions:
And Kent B. has a good article: MVVM Infrastructure: DelegateCommand