简体   繁体   中英

ICommand - RelayCommand CanExecute method does not update button IsEnabled property

I have the following implementation of an RelayCommand 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 use 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 bind the comman to a button:

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

My Problem is that the button just gets enabled once i click on any control in the UI. But what i need is that the button gets enabled once my _data.Counter > 0 applies. So from my research it seems that i need to implement CommandManager.InvalidateRequerySuggested(); or use the RelayCommand.RaiseCanExecuteChanged() .

I would like to know if this two ways are the only ways to notify the UI to refresh the bindings.

Also i would like to ask how i would have to implement the RelayCommand.RaiseCanExecuteChanged() in my current case. Where and how should i raise it to ensure that the UI changes the button state if the condition is given.

Thanks in advance.

when using CommandManager.RequerySuggested you can force CommandManager to invoke RequerySuggested event by calling CommandManager.InvalidateRequerySuggested()

or you may perhaps implement RaiseCanExecuteChanged . this may be more reliable method to trigger the same.

example

internal class RelayCommand : ICommand
{
    ...

    public event EventHandler CanExecuteChanged;

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

    ...
}

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

ResetCounter.RaiseCanExecuteChanged();

additionally you may also want to read How does CommandManager.RequerySuggested work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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