mvvmlight icon indicating copy to clipboard operation
mvvmlight copied to clipboard

RelayCommand.RaiseCanExecuteChanged() does nothing under Xamarin

Open AndrueCope opened this issue 5 years ago • 3 comments

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 :-/

AndrueCope avatar Aug 20 '18 11:08 AndrueCope

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?

olitee avatar Aug 21 '18 12:08 olitee

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.

AndrueCope avatar Aug 21 '18 12:08 AndrueCope

@olitee is correct, I had to run the RaiseCanExecuteChanged on the UI thread and it worked as expected afterwards.

Device.BeginInvokeOnMainThread(() => {
    ((RelayCommand) MyCommand).RaiseCanExecuteChanged();
});

StephanBis avatar Nov 15 '18 10:11 StephanBis