ICommand - RelayCommand CanExecute method does not update IsEnabled property

I have the following RelayCommand implementation in my ViewModel:

RelayCommand _resetCounter;

private void ResetCounterExecute()
{
    _data.ResetCounter();
}

private bool CanResetCounterExecute()
{
    if (_data.Counter > 0)
    {
        return true;
    }
    else
    {
        return false;
    }

}

public ICommand ResetCounter
{ 
    get 
    {

        if (_resetCounter == null)
        {
            _resetCounter = new RelayCommand(this.ResetCounterExecute,this.CanResetCounterExecute);
        }
        return _resetCounter; 
    }
}

      

By calling _data.ResetCounter();

in the ResetCounterExecute method I reset the counter value to 0 in my model.

And this is the implementation of my RealyCommand class that I am using based on samples.

internal class RelayCommand : ICommand
{
    readonly Action _execute;
    readonly Func<bool> _canExecute;

    public RelayCommand(Action execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested += value;
        }
        remove
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }

    public void Execute(object parameter)
    {
        _execute();
    }
}

      

In XAML, I'll bind the comman to the button:

<Button Name="btnResetCount" Content="Reset" Command="{Binding Path=CounterViewModel.ResetCounter}" Click="btnResetCount_Click">

      

My problem is that the button just gets activated as soon as I click on any control in the UI. But I need the button to turn on after mine _data.Counter > 0

. So from my research it seems like I need to implement CommandManager.InvalidateRequerySuggested();

or use RelayCommand.RaiseCanExecuteChanged()

.

I would like to know if these two are the only ways to notify the UI to update the bindings.

Also I would like to ask how I would have to implement RelayCommand.RaiseCanExecuteChanged()

in my current case. Where and how should I raise it so that the UI changes the state of the button if the condition is set.

Thanks in advance.

+3


source to share


1 answer


when in use CommandManager.RequerySuggested

you can make the CommandManager raise the RequerySuggested event by calling CommandManager.InvalidateRequerySposed ()

or you can implement RaiseCanExecuteChanged

. it might be a more reliable way to run the same thing.

Example

internal class RelayCommand : ICommand
{
    ...

    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = CanExecuteChanged;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    ...
}

      



and if you want to invalidate or _data.Counter changes, call

ResetCounter.RaiseCanExecuteChanged();

      

Additionally, you can also read How Does CommandManager.RequeryS Suggest Work?

+1


source







All Articles