I have the following code defined in a viewmodel. I think that the SaveAsync of type Func<Task>
is getting converted to Action since RelayCommand takes an Action not a Func<Task>
but I'm not clear on the implications of that.
1) Does RelayCommand need to be replaced with an asynchronous version (RelayCommandAsync)? 2) What exactly is the current code doing regarding asynchrony? 3) What if anything could/should I change to improve/correct it?
private ICommand _saveCommand;
public ICommand SaveCommand
{
get { return _saveCommand ?? (_saveCommand = new RelayCommand(async () => await SaveAsync(), CanSave)); }
}
public bool CanSave()
{
return !IsBusy;
}
private async Task SaveAsync()
{
IsBusy = true;
try
{
await _service.SaveAsync(SomeProperty);
}
catch ( ServiceException ex )
{
Message = "Oops. " + ex.ToString();
}
finally
{
IsBusy = false;
}
}
Thanks!
EDIT: After some experimenting it does appear that the async method itself works as it should. And it did not make a difference whether async/await was included in the lambda nor whether the method was defined as async Task
or async void
.
However, what does not work correctly is the canExecute
predicate functionality that automatically enables/disables the control binding to the command. What happens is that the button is correctly disabled while the async method runs but it is not enabled afterwards. I have to click somewhere on the window once and then it becomes enabled again.
So it appears an async version of RelayCommand is required for full functionality, i.e. so canExecute
can do its thing correctly.