Reputation: 4777
I have the following code in my WPF Application that I use to enable or disable buttons on my UI
XAML
<Button x:Name="FirstButton" Command="{x:Static local:MyClass.CommandOne}"/>
<Button x:Name="FirstButton" Command="{x:Static local:MyClass.CommandTwo}"/>
Code Behind
CommandBindings.Add(new CommandBinding(CommandOne, CommandOne_Executed, CommandOne_CanExecute));
CommandBindings.Add(new CommandBinding(CommandTwo, CommandTwo_Executed, CommandTwo_CanExecute));
public static readonly RoutedUICommand CommandOne = new RoutedUICommand();
public static readonly RoutedUICommand CommandTwo = new RoutedUICommand();
private void CommandOne_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e != null)
e.CanExecute = (_currentValue > 1);
}
private void CommandTwo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e != null)
e.CanExecute = (_currentValue > 100);
}
Worker Code
private async Task DoSomeWork(int value)
{
await Task.Run(() =>
{
// Do some work on value
_currentValue = value
}
}
What I find is that when the values of _currentValue change due to some processing sometimes the CommandOne_CanExecute and CommandTwo_CanExecute functions do not get called. If I then e.g. move the UI they will then be called. How can I ensure that these are called everytime.
Upvotes: 0
Views: 1573
Reputation: 169400
You could call the CommandManager.InvalidateRequerySuggested()
method to invalidate all commands.
What you should do however is to implement your own command - it is simply a class that implements the ICommand
interface - and raise the CanExecuteChanged
event of the command whenever you want the CanExecute
method to get called.
Or you could use any of the implementations of the ICommand
that are included in any of the MVVM frameworks out there. You could for example take a look at how the RelayCommand
class is implemented in MvvmLight: https://github.com/paulcbetts/mvvmlight/blob/master/GalaSoft.MvvmLight/GalaSoft.MvvmLight%20(NET35)/Command/RelayCommand.cs.
It has a RaiseCanExecuteChanged()
method that you can call to raise the CanExecuteChanged
event of the command. This will cause the CanExecute
method to get invoked and the command to be invalidated.
The built-in RoutedUICommand
class has no such method I am afraid.
Upvotes: 3
Reputation: 1985
You need to create a property for CurrentValue instead of a variable and raisecanexecutechanged event Try below code
private int _currentValue = false;
public bool CurrentValue
{
get { return _currentValue; }
set
{
if(_currentValue != value)
CommandManager.InvalidateRequerySuggested();
SetProperty(ref _currentValue, value);
}
}
CommandBindings.Add(new CommandBinding(CommandOne, CommandOne_Executed, CommandOne_CanExecute));
CommandBindings.Add(new CommandBinding(CommandTwo, CommandTwo_Executed, CommandTwo_CanExecute));
public static readonly RoutedUICommand CommandOne = new RoutedUICommand();
public static readonly RoutedUICommand CommandTwo = new RoutedUICommand();
private void CommandOne_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e != null)
e.CanExecute = (CurrentValue > 1);
}
private void CommandTwo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e != null)
e.CanExecute = (CurrentValue > 100);
}
private async Task DoSomeWork(int value)
{
await Task.Run(() =>
{
// Do some work on value
CurrentValue = value
}
}
Upvotes: 0