In MVVM where the ViewModels update the Views via INotifyPropertyChanged events, there doesn’t seem to be much room for the cool feature of async/await; executing the continuation on the captured synchronization context of the invoker.
So, if this is the case, then who will actually use the features of async/await in a modern UI based app? In this context, “who” can also mean what pattern, e.g. MVC-variation.
I can think of the following as a good way of using TAP
ViewModel.Age
{
set {
await Model.SetAge(value);
NotifyPropertyChanged("Age");
}
}
however, having this run on the captured syncContext, does not really help out much.
Actually, we could put all this in the model instead.
Model.Age
{
set {
await SetAge(value);
NotifyPropertyChanged("Age");
}
}
and now, we would really like the syncContext NOT to be the captured one.
Actually, having
INotifyPropertyChanged.PropertyChangedraised in the UI synchronization context is required for data binding.async/awaitdo force you to make a distinction between properties (which represent the current state and are always synchronous) and commands (which represent actions and may be synchronous or asynchronous). Property getters and setters cannot beasync, so your example code with an “async set” is not a possible approach.asyncenables asynchronous commands. You can use command binding to asynchronously handle routed commands, or pass anasyncdelegate to aDelegateCommand, or use your ownICommandimplementation. Whichever way you’ll do it, you end up with anasync voidcommand event handler.A realistic example is to have the VM properties set the M properties in-memory, and have a
SaveCommandwith anasynchandler. It’s common to haveasynchandlers interact with an additional VM property (SaveInProgressor maybe a commonBusyshared with otherasynchandlers) so that the UI can respond appropriately when the command is in progress (usually at least causingCanExecuteto returnfalse).So your
asynchandler ends up looking something like:Note that the VM properties (
ErrorandBusy) are updated in the captured UI synchronization context.This illustrates the central concept of
asyncMVVM: commands may beasync, but the properties (such asBusy) always represent the current state.If you’re adding
asyncto an existing MVVM app, you’ll find yourself with several additional properties indicating business and possibly also progress updates (e.g., percent complete). Depending on your application, you may permit multiple asynchronous operations at the same time. You’ll need to think of good ways to add this information to your Views; I find this to be the most challenging part ofasyncMVVM apps.