简体   繁体   English

DelegateCommand 的 CanExecute 逻辑

[英]CanExecute Logic for DelegateCommand

Update: The focus became MVVM instead of the actual question so I'm updating it.更新:焦点变成了 MVVM 而不是实际问题,所以我正在更新它。

I'm having a problem with CanExecute for DelegateCommand .我在使用CanExecute for DelegateCommand遇到问题。 It doesn't update before I call RaiseCanExecuteChanged , is this the desired behavior?在我调用RaiseCanExecuteChanged之前它不会更新,这是所需的行为吗?

在此处输入图片说明

I uploaded a simple sample project reproducing this problem here : http://dl.dropbox.com/u/39657172/DelegateCommandProblem.zip我在这里上传了一个简单的示例项目来重现这个问题: http : //dl.dropbox.com/u/39657172/DelegateCommandProblem.zip

The problem is this, I have two Buttons like this.问题是,我有两个这样的Buttons One is Binding Command to a RelayCommand implementation and the other is binding to the Prism implementation of DelegateCommand一种是将Command绑定到RelayCommand实现,另一种是绑定到DelegateCommand的 Prism 实现

<Button Command="{Binding DelegateSaveCommand}"/>
<Button Command="{Binding RelaySaveCommand}"/>

The ViewModel ICommands ViewModel ICommands

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

and the CanExecute method/predicateCanExecute方法/谓词

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

Both are using the property HasChanges .两者都使用属性HasChanges When HasChanges is updated, only the CanSaveRelay updates.HasChanges更新时,只有CanSaveRelay更新。 Is this the way it's meant to be?这是应该的方式吗?

As it already was mentioned, this is intended behavior of DelagateCommand , not a bug.正如已经提到的,这是DelagateCommand预期行为,而不是错误。 DelegateCommand doesn't raise CanExecuteChanged event automatically, you have to raise that event manually by calling RaiseCanExecuteChanged when appropriate. DelegateCommand不会自动引发CanExecuteChanged事件,您必须在适当的时候通过调用RaiseCanExecuteChanged手动引发该事件。 Whereas RelayCommand relays on CommandManager.RequerySuggested event for that.RelayCommandCommandManager.RequerySuggested事件上中继。 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 to PropertyChanged event on the model, etc) I have created the following simple wrapper that ensures that the CanExecute method of the wrapped command is executed automatically on CommandManager.RequerySuggested event:因为当它是不是很方便,或者没有合适的地方调用情况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; }
    }
}

You can use it like this:你可以这样使用它:

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

If you want to stick to DelegateCommand you can use ObservesCanExecute :如果你想坚持DelegateCommand你可以使用ObservesCanExecute

DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate).ObservesCanExecute(CanSaveDelegate);

Note that there is also ObservesProperty available if you are using a property for your CanExecute check.请注意,也有ObservesProperty可用,如果你正在使用您的CanExecute检查属性。 But then your property has to call NotifyPropertyChanged.但随后您的财产必须调用 NotifyPropertyChanged。

There is a bug in the DelegateCommand provided by Prism which doesn't raise the CanExecute event. Prism 提供的 DelegateCommand 中有一个错误,它不会引发 CanExecute 事件。 I beat my head against the wall for a day until I dove into the DelegateCommand class provided by the Prism framework.我把头靠在墙上一天,直到我深入到 Prism 框架提供的DelegateCommand类。 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.另一种方法是使用其他 RelayCommand 框架之一。

Edit编辑
Rather than reposting the code, there are other SO questions that provide resolutions:除了重新发布代码之外,还有其他提供解决方案的 SO 问题:

And Kent B. has a good article: MVVM Infrastructure: DelegateCommand并且 Kent B. 有一篇很好的文章: MVVM Infrastructure: DelegateCommand

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM