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.
source to share
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?
source to share