Custom Command update CanExecute

2019-07-17 07:35发布

问题:

I have to use this Command in a WPF application (i dont like it really but if i have to -> i have to ): http://wpftutorial.net/DelegateCommand.html

But the main problem I have here is that I don t want to have in nearly every line of my code a call to the

RaiseCanExecuteChanged()

method. So what could I do to do that auto like RoutedUICommand does.

I have a lot of databindings and as example if Foo.FooProp != null Command can execute. But I want as less code as possible and so I would have to register events everywhere or update commands all over my application....

回答1:

You could implement a form of DelegateCommand which invokes the delegates added to CanExecuteChanged everytime there is a change of possible consequence in the UI. This example uses CommandManager.RequerySuggested.

public class AutoDelegateCommand : DelegateCommand, ICommand
{
    public AutoDelegateCommand(Action<object> execute)
        : base(execute)
    {
    }        

    public AutoDelegateCommand(Action<object> execute, Predicate<object> canExecute)
        : base(execute, canExecute)
    {
    }

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

I think I've seen an example like this before, perhaps in the MVVMLight toolkit?



回答2:

When I use a DelegateCommand, I just manually raise the CanExecuteChanged in the PropertyChange event whenever a property the command relies on changes.

Here's an example I did a few days ago where the CanExecute was based off the IsLoading and IsValid properties:

public MyViewModel()
{
    this.PropertyChanged += MyViewModel_PropertyChanged;
}

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "IsLoading":
        case "IsValid":
            ((DelegateCommand)MyCommand).RaiseCanExecuteChanged();
            break;
    }
}


public ICommand MyCommand
{
    get
    {
        if (_myCommand == null)
            _myCommand = new DelegateCommand(Run, CanRun);

        return _myCommand;
    }
}

public bool CanRun()
{
    return this.IsValid && !IsLoading;
}

I find this keeps the logic easy to follow and maintain, and it only checks the CanExecuteChanged() method when the relevant properties change.



标签: wpf command