mvvmlight
mvvmlight copied to clipboard
RelayCommand.RaiseCanExecuteChanged() does nothing under Xamarin
We are porting some WPF code to Xamarin and at one point we have the following method:
public void RaiseCanExecuteChanged() { foreach (var cmd in _relayCommands) { cmd.RaiseCanExecuteChanged(); } }
This works fine under WPF but under Xamarin the exact same code (it's a shared assembly) does nothing. None of the command's canExecute() methods are called. The methods are being called when first binding to the commands but we can't call them after that :-/
I know under WPF the cmd.RaiseCanExecuteChanged() method must be called from the UI thread. If it isn't, no exception is thrown - but the binding engine doesn't react (or call CanExecute()). Are you sure your ported version is calling that method from the main/UI thread?
Yes. It's being called from a lambda that is passed to Xamarin.Forms.Device.BeginInvokeOnMainThread(). I worked around it by calling PropertyChanged for each bound command instead:
foreach (var prop in GetType().GetProperties().Where(p => p.PropertyType == typeof(ICommand))) { RaisePropertyChanged(prop.Name); }
The commands don't actually change but that seems to cause Xamarin to call CanExecute() anyway. Also I don't know if this is relevant but I can step into RaiseCanExecuteChanged() with WPF but with mobile I can't.
@olitee is correct, I had to run the RaiseCanExecuteChanged on the UI thread and it worked as expected afterwards.
Device.BeginInvokeOnMainThread(() => {
((RelayCommand) MyCommand).RaiseCanExecuteChanged();
});