Why CanxxxCommandExecute is fired so much times? - c#

I've got some problems with Commands and their CanXXXExecute... I was thinking it was a Catel (MVVM framework) problem but I've tested myself with a standard WPF application and it still happen..
In the example I'm posting I've got the "CanClickCommandExecute" method called 2 times at load (one at constructor and I agree with this, the other one I think at view's load) and 3 times when I click the button!!
Here's the XAML
<Window x:Class="StandardWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Command="{Binding ClickCommand}" Content="ClickMe!" Background="Teal"></Button>
</Grid>
The .cs
public partial class MainWindow : Window
{
public ICommand ClickCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
ClickCommand = new RelayCommand(OnClickCommandExecute,CanClickCommandExecute);
}
private bool CanClickCommandExecute()
{
Debug.WriteLine("Standard OnClickCommandExecute fired!");
return true;
}
private void OnClickCommandExecute()
{
//something weird in there!
}
}
The RelayCommand (taken from here)
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
Why this happen? How can I spot what's happening? In my real case I use the CanXXX to perform validation...in that case I got validation fired a lot of times and on some object can take a lot of time

Why CanxxxCommandExecute is fired so much times?
Because you're raising the CanExecuteChanged method several times, and so CanExecute is evaluated by wpf several times.
You're not directly raising the event yourself, but CommandManager.RequerySuggested does it.
As the documentation says Occurs when the CommandManager detects conditions that might change the ability of a command to execute. CommandManager.RequerySuggested will guess the possible events which might need to update the button's state. It may happen many times, for instance minimizing the app will trigger it; etc.
If you want to take control over when CanExecute is called, then raise the event manually. Don't use CommandManager.RequerySuggested.

If you look at the .NET Framework source code, CommandManager doesn't detect conditions by itself, rather when Keyboard.KeyUpEvent, Mouse.MouseUpEvent, Keyboard.GotKeyboardFocusEvent, or Keyboard.LostKeyboardFocusEvent occurs, it will fire the CanExecute method; obviously, this can happen multiple times.

Related

Should CanExecute work forever or just when property is changed?

I am working on a calculator. My view contains 16 Buttons and 1 TextBox:
TextBox's Text property is bound to the UserInput property in ViewModel:
<TextBox x:Name="InputTextBox"
Grid.Row="0"
Background="#ECDBBA"
Foreground="#191919"
FontSize="30"
Text="{Binding UserInput, UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True"
VerticalContentAlignment="Center"/>
public class ViewModel : INotifyPropertyChanged
{
public AddTextCommand AddTextCmnd { get; set; }
public ClearTextCommand ClearTextCmnd { get; set; }
public ShowResultCommand ShowResultCmnd { get; set; }
private string _userInput = "0";
public string UserInput
{
get { return _userInput; }
set
{
if (UserInput != value)
{
_userInput = value;
OnPropertyChanged("UserInput");
}
}
}
public ViewModel()
{
AddTextCmnd = new AddTextCommand(this);
ClearTextCmnd = new ClearTextCommand(this);
ShowResultCmnd = new ShowResultCommand(this);
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I have 3 commands: One to add text to TextBox, another to show the result, and a last one to clear the TextBox. AC and "=" buttons (see screenshot) are bound to ClearTextCommand and ShowResultCommand.
public class ShowResultCommand : ICommand
{
private ViewModel _viewModel;
public ShowResultCommand(ViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
if (_viewModel.UserInput != "0")
return true;
else
return false;
}
public void Execute(object parameter)
{
DataTable calculator = new DataTable();
_viewModel.UserInput = calculator.Compute(_viewModel.UserInput, null).ToString();
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
}
public class ClearTextCommand : ICommand
{
private ViewModel _viewModel;
public ClearTextCommand(ViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
if (_viewModel.UserInput != "0")
return true;
else
return false;
}
public void Execute(object parameter)
{
_viewModel.UserInput = "0";
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
The program works well, but 2 commands share a problem. I don't know if it is my ignorance or not, but I didn't find anything in Google. I thought that my CanExecute methods work only when UserInput changed (property changed), but I put a breakpoint on the CanExecute methods of my commands and saw that they work forever in debug, like once UserInput is changed, ShowResultCommand and ClearTextCommand's CanExecute methods work forever, they are called again and again in a loop. I am wondering if they should work this way? Shouldn't they be called just when UserInput is changed? This doesn't cause any error in my program, but I think there is something wrong with my commands.
So basically question is:
Should CanExecute work in a loop while my app is running or should it work when a property related to the method is changed? If it should work in a loop, then everything is fine, but if not what is wrong with my commands?
I thought that my CanExecute methods work only when UserInput changed(property changed).
Yes and no. Your commands delegate the CanExecuteChanged event to the RequerySuggested event of CommandManager. This is a common approach. The CommandManager is a WPF framework type responsible for:
Provides command related utility methods that register CommandBinding and InputBinding objects for class owners and commands, add and remove command event handlers, and provides services for querying the status of a command.
The RequerySuggested event is only raised under a few not well documented circumstances:
The CommandManager only pays attention to certain conditions in determining when the command target has changed, such as change in keyboard focus.
As you can see this is very vage and there are situations, where the CommandManager simply cannot know:
In situations where the CommandManager does not sufficiently determine a change in conditions that cause a command to not be able to execute, InvalidateRequerySuggested can be called to force the CommandManager to raise the RequerySuggested event.
In summary, yes, the RequerySuggested event is raised when user input changes and on other input related events e.g. in a TextBox or bound properties change, but not in all situations. From a different perspective, the CommandManager determines when it needs to raise the event only on general triggers, so often it will invalidate all can execute states, although most or even no command might even be affected. It is not targeted to the specific case, like a distinct property that you want to observe for changes, but like a watering pot. This can of course make a difference in performance, although negligible in the majority of applications.
I put breakpoint on CanExecute methods of my commands and saw that they work forever in debug
Yes and by now you know exactly why. In debug mode when a breakpoint is hit, the debugger or IDE is brought into foreground meaning the keyboard focus changes. When you switch back to your application being debugged, the keyboard focus changes again...and again...and again. Since the CommandManager raises the RequerySuggested event on keyboard focus, you will constantly trigger CanExecute and hit the breakpoint. The same may happen on window activation as well.
A Different Command Approach
There is another very common approach for notifying can execute changed. In your example, you rely on the CommandManager to do its best for all commands. However, you could also take responsibility yourself and explicitly invalidate can execute through another public method.
public class RelayCommand<T> : ICommand
{
private readonly Predicate<T> _canExecute;
private readonly Action<T> _execute;
public RelayCommand(Action<T> execute) : this(execute, null)
{
_execute = execute;
}
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute((T)parameter);
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
Here you assume that you know exactly when to update your own command. Instead of asking "Dear command manager, please tell me when to update" you say "Update these specific commands now". For this you have to call RaiseCanExecuteChanged for each affected command in your properties.
public string UserInput
{
get { return _userInput; }
set
{
if (UserInput != value)
{
_userInput = value;
OnPropertyChanged("UserInput");
AddTextCmnd.RaiseCanExecuteChanged();
ClearTextCmnd.RaiseCanExecuteChanged();
ShowResultCmnd.RaiseCanExecuteChanged();
}
}
}
This mechanism has a few advantages over the RequerySuggested event.
You decide exactly when commands are updated.
Only commands that are really affected are updated.
It is much easier to comprehend the dependencies in your view model.
Potential performance benefit from reducing unnecessary updates.
No reliance on an external component and hidden magic or vage assumptions.
A Hint On DRY and Reusability
As of now, all of your commands contain duplicated logic, violating the Don't repeat yourself principle, in short DRY. This makes maintenance much harder. Instead you should at least extract a common, reusable command type as shown above to improve your code. You do not even have to implement one yourself, there are plenty of frameworks, libraries and NuGet packages available already, e.g. Microsoft.Toolkit.Mvvm, see its documentation here.
Here is an example how it would look like for your clear text command:
public ViewModel()
{
ClearTextCmnd = new RelayCommand(ExecuteClearText, CanExecuteClearText);
// ...other commands.
}
public ICommand ClearTextCmnd { get; set; }
public bool CanExecuteClearText()
{
return UserInput != "0";
}
public void ExecuteClearText()
{
UserInput = "0";
}
For simplicity I used a RelayCommand implementation without an extra parameter, as you do not use it currently. It is the same as the command above, only without the parameter for each method.
As asked in the comments, this would be the RelayCommand implementation without parameter.
public class RelayCommand : ICommand
{
private readonly Func<bool> _canExecute;
private readonly Action _execute;
public RelayCommand(Action execute) : this(execute, null)
{
_execute = execute;
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

How to Disable and Enable Button in C# WPF using MVVM

i have one view model name as "SettingsViewModel" and in that view model I am writing the function for button click ( bUpdate() )
namespace
{
class SettingsViewModel : Notifyable
{
public Settings settings
{
get => _settings;
set
{
_settings = value;
OnPropertyChanged();
}
}
private Settings _settings = Settings.Default;
private IWindowManager _windowManager;
public SettingsViewModel(IWindowManager windowManager)
{
_windowManager = windowManager;
}
protected override void OnClose()
{
base.OnClose();
settings.Save();
}
CopyFilesRecursively(serverDirectorty, localDirectory){
// DO SOMETHING
}
public void bUpdate()
{
CopyFilesRecursively(serverDirectorty, localDirectory);
}
}
}
I want to disable button click when copying of the files is start and when copying is done I want to re enabled the button click.
Below is my XML (SettingsView.xml) for the button
<Button Content="{x:Static p:Resources.update}" HorizontalAlignment="Right" Command= "{s:Action bUpdate }" />
How can i do that with the help of Binding?
Since you need the MVVM approach, the ideal way would be to set the DataContext of the View/UserControl to the instance of the ViewModel (tell me if you want how-to in comments further, I'll explain) and then bind to a property which is an instance of an ICommand implementation like this:-
View/UserControl:
<Button Content="{x:Static p:Resources.update}"
HorizontalAlignment="Right"
Command="{Binding Update}" />
ViewModel:
public ICommand Update => new RelayCommand(HandleUpdate, CanUpdate);
private bool _isRunning = false;
private void HandleUpdate()
{
_isRunning = true;
CommandManager.InvalidateRequerySuggested();
Task.Run(() =>
{
// Update Button click logic goes here
CopyFilesRecursively(serverDirectorty, localDirectory);
Application.Current.Dispatcher.Invoke(() =>
{
_isRunning = false;
CommandManager.InvalidateRequerySuggested();
});
});
}
private bool CanUpdate()
{
return !_isRunning;
}
The _isRunning flag just maintains the current running state information and the InvalidateRequerySuggested invocation on the CommandManager forces the View to force the CanExecuteChanged event on the ICommand.
The Task.Run ensures that your long-running process doesn't block the UI thread and the current dispatcher invocation is a guard against non-UI thread manipulating Xaml elements that could potentially cause an issue.
Here is a parameterless implementation of the ICommand interface:
public class RelayCommand : ICommand
{
readonly Func<Boolean> _canexecute;
readonly Action _execute;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<Boolean> canexecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canexecute = canexecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canexecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canexecute != null)
CommandManager.RequerySuggested -= value;
}
}
public Boolean CanExecute(Object parameter)
{
return _canexecute == null ? true : _canexecute();
}
public void Execute(Object parameter)
{
_execute();
}
}
You could refactor the boolean flag and optimize your way but this is how we usually de-couple the viewmodel logic from the view code!
P.S.:
There are further ways to pass command parameters via the command binding as well, you could look into that when you need so or I could clarify in comments.
Also, there's no exception handling in the task run currently, do consider aggregate exception catching furthermore.
Well, I'm wondering a bit about your code example. Guess you will run into a "UI is blocked" issue soon. Anyhow, you can get around step by step.
Of course you can do that by binding. Note you can bind nearly any item property to a property in your VM. So for simplicity, you may do it like this
<Button IsEnabled={Binding MyButtonIsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="{x:Static p:Resources.update}" HorizontalAlignment="Right" Command= "{s:Action bUpdate }" />
For the VM side, I assume you are using some MVVM framework Nuget package, and/or have Fody enabled taking care about the plumbing of the INotifyPropertyChanged event. If not, ammend the MyButtonIsEnabled property with a backing field like your other VM properties:
public bool MyButtonIsEnabled {get; set;}
public void bUpdate()
{
MyButtonIsEnabled = false;
CopyFilesRecursively(serverDirectorty, localDirectory);
MyButtonIsEnabled = true;
}
So far, so nice - but won't work as expected, because the bUpdate function is a synchronous function. It will not return until work is done. Hence, your complete UI will not be responsive and the button won't get a time slice to disable and re-enable.
Rather you should work with an ICommands resp. IYourMVVMFrameworkCommand (I'm favoring Catel) like:
(view)
<Button Command="{Binding CopyMyFilesCommand}" Content="...whatever..."/>
(VM)
public ICatelCommand CopyMyFilesCommand { get; private set; }
MyVieModel() // constructor
{
...
CopyMyFilesCommand = new TaskCommand(OnCopyMyFilesCommand);
...
}
private async Task OnCopyMyFilesCommand()
{
await Task.Run(bUpdate).ConfigureAwait(false);
}
Using Catel, the TaskCommand constructor takes a second delegate parameter deciding if the ICommand can be executed. Wiring it as
CopyMyFilesCommand = new TaskCommand(OnCopyMyFilesCommand, () => MyButtonIsEnabled);
Will disable the command which in turn disables the button without the need of binding the IsEnabled property.

Data binding in MVVM WPF OnButtonClick

I am using MVVM in my WPF application and I have a problem with data binding. I am considering binding user actions to data operations (in my case adding record to database). If I use heavy coupling between CommandClass and ViewModelClass everything works fine. My CommandClass in this case looks like this:
public class ButtonCommand : ICommand
{
private readonly UserViewModel _userViewModel;
public ButtonCommand(UserViewModel viewModel)
{
_userViewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_userViewModel.AddUser();
}
public event EventHandler CanExecuteChanged;
}
My heavy coupling in ViewModelClass looks like this:
private readonly ButtonCommand _buttonCommand;
public UserViewModel()
{
_buttonCommand = new ButtonCommand(this);
}
public ICommand btnClick
{
get { return _buttonCommand; }
}
My XAML coupling on button click (take a look on a Command section):
<Page.Resources>
<viewModel:UserViewModel x:Key="UserObj" TxtFirstName="" TxtLastName="" TxtEmail="" TxtPassword=""/>
</Page.Resources>
....
<Button Content="Submit" HorizontalAlignment="Left" Margin="42,231,0,0" VerticalAlignment="Top" Width="75" Command="{Binding btnClick, Mode=OneWay, Source={StaticResource UserObj}}"/>
And I have such an output (take a look at Submit button): Window.
After I make changes to my CommandClass and ViewModelClass (to make them more general and reusable), but leave my XAML coupling the same the Submit button becomes unavailable after runnig my application. After changes CommandClass looks like this:
public class ButtonCommand : ICommand
{
private readonly Action _executionMethod;
private readonly Func<bool> _executeOrNot;
public ButtonCommand(Action executionMethod, Func<bool> executeOrNot)
{
_executionMethod = executionMethod;
_executeOrNot = executeOrNot;
}
public bool CanExecute(object parameter)
{
return _executeOrNot();
}
public void Execute(object parameter)
{
_executionMethod();
}
public event EventHandler CanExecuteChanged;
}
My ViewModelClass after changes:
private readonly ButtonCommand _buttonCommand;
public UserViewModel()
{
_buttonCommand = new ButtonCommand(AddUser, IsValidInputForRegistration);
}
public ICommand btnClick
{
get { return _buttonCommand; }
}
XAML I leave the same. The output I have is next (take a look at Submit button): WindowWithChanges.
Can anyone provide me with some information, why button became unavailable and where do I mess up?
First, try IsValidInputForRegistration to always return true. That will prove that your implementation of IButton (i.e. your ButtonCommand class) works fine.
If that works, what's happening to your program is the IsValidInputForRegistration passes the state for your _buttonCommand during initialization and it will stay on that state since it doesn't query if the IsValidInputForRegistration have changed states.
To achieve querying of states, you can implement the EventHandler CanExecuteChanged like so:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
You can look into msdn for what CommandManager.RequerySuggested does. But I think the description says it all. :)
Occurs when the CommandManager detects conditions that might change
the ability of a command to execute.

Simple explanation of how to use commands with a button click in WPF

I'm a starter and I'm trying to use commands instead of Click="Display".
<Button Content ="Click Me!" Command = "{Binding ClickMeCommand}" />
How would I write the method to use the command? Say I want to display a message like "clicked!" in the console when the button is clicked. I'm looking for the simplest implementation that is easy to understand please. I've tried looking at tutorials but they over complicate things and it is hard for me to understand.
One way would be like this:
Create your ViewModel :
public class MainViewModel
{
public MainViewModel()
{
}
private ICommand clickMeCommand;
public ICommand ClickMeCommand
{
get
{
if (clickMeCommand == null)
clickMeCommand = new RelayCommand(i => this.ClickMe(), null);
return clickMeCommand;
}
}
private void ClickMe()
{
MessageBox.Show("You Clicked Me");
}
}
Or initialize it in the constructor.
First paramater of the Command is the method that will be executed when you click the button you binded your command to. The second parameter is the method that enables/disables the button based on the logic. If you would like the button to be enabled at all times just set:
In your MainWindow code behind set the MainViewModel as the datacontext of your mainwindow.
public partial class MainWindow : Window
{
public MainWindow()
{
MainViewModel vm = new MainViewModel();
InitializeComponent();
this.DataContext = vm;
}
}
And the RelayCommand class(this is just an implementation of the ICommand Interface). You can use other implementation of ICommand if you want.
public class RelayCommand : ICommand
{
readonly Action<object> execute;
readonly Predicate<object> canExecute;
public RelayCommand(Action<object> executeDelegate, Predicate<object> canExecuteDelegate)
{
execute = executeDelegate;
canExecute = canExecuteDelegate;
}
bool ICommand.CanExecute(object parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
event EventHandler ICommand.CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
void ICommand.Execute(object parameter)
{
execute(parameter);
}
}

WPF UI not updating after incoming WCF message

I have an MVVM app, where my ViewModel PingerViewModel processes incoming WCF Ping() messages. Processing such a message happens on a thread of Scheduler.Default's thread pool.
Semantically, incoming WCF messages change a bound property CanPing and raise the PropertyChanged event for said property.
But my UI is not updating until it receives some UI event, e.g. focusing/clicking the window, etc.
How do I make it update as soon as the event is fired?
I have tried raising the PropertyChanged event...
on the Application's Dispatcher,
using a SynchronizationContext
without any luck.
I also verified that the bound property is indeed set to the proper value, and that there is indeed a listener consuming my PropertyChanged event.
Here's some code (full code on github):
part of my view's MainWindow.xaml:
It might be worth noting that the bound Command does not actually play a role in producing the incoming WCF message.
<Button Content="Ping" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="PingBtn" VerticalAlignment="Top" Width="75" AutomationProperties.AutomationId="Ping"
IsEnabled="{Binding CanPing}"
Command="{Binding PingCommand}" />
part of my views MainWindow.xaml.cs
public MainWindow()
{
DataContext = new PingerViewModel();
InitializeComponent();
}
part of my ViewModel
public class PingerViewModel : INotifyPropertyChanged
public PingerViewModel()
{
Pinger = new Pinger(true);
PingCommand = new PingerPingCommand(this);
//...
}
public bool CanPing
{
get
{
if (Pinger == null) return false;
return Pinger.CanPing;
}
}
public void Ping()
{
_pingClient.Channel.Ping();
Pinger.CanPing = false;
OnPropertyChanged("CanPing");
}
protected virtual void OnPong(PongEventArgs e)
{
Pinger.CanPing = true;
OnPropertyChanged("CanPing");
}
public Pinger Pinger { get; private set; }
public ICommand PingCommand { get; private set; }
//...
}
I think you need to remove IsEnabled="{Binding CanPing}" from your button.
Binding to the command is enough as the ICommand object contains CanExecute and the CanExecuteChanged event handler.
I would create a CanExecute boolean inside your Command class, and implement INotifyPropertyChanged also on this class. Something like this:
public class PingCommand : ICommand, INotifyPropertyChanged
{
private bool _canExecute;
public bool CanExecute1
{
get { return _canExecute; }
set
{
if (value.Equals(_canExecute)) return;
_canExecute = value;
CanExecuteChanged.Invoke(null, null);
OnPropertyChanged("CanExecute1");
}
}
public void Execute(object parameter)
{
//whatever
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Then, on the Ping/Pong methods inside your ViewModel, update this property inside your Command:
public void Ping()
{
_pingClient.Channel.Ping();
Pinger.CanPing = false;
PingCommand.CanExecute1 = false;
OnPropertyChanged("CanPing");
}
protected virtual void OnPong(PongEventArgs e)
{
Pinger.CanPing = true;
PingCommand.CanExecute1 = true;
OnPropertyChanged("CanPing");
}
if your CanPing Property and the CanExecute methode for your PingCommand both return TRUE it should work.
sometimes the Delegate/RelayCommand implementation give the possibility to call RaiseCanExecuteChanged() - try this if the statement above is true for both and its not working
btw this is called within the RaiseCanExecuteChanged()
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
You can use RaiseCanExecuteChanged() method of the said property to update.
Eg:
this.PingCommand.RaiseCanExecuteChanged();
Try this, I hope it will solve your problem.

Categories