It doesn't, you need to use a 3rd party library that provides async commands. Personally I like Nito.Mvvm.Async, it gives you a AsyncCommand you can use and bind your functions to. The button will be disabled while the async function runs and will re-enable once the function is complete.
<ContentPage.ToolbarItems>
<ToolbarItem Text = "Done" Command="{Binding DoneCommand}" />
<ToolbarItem Text = "Cancel" Command="{Binding CancelCommand}" Priority="1" />
</ContentPage.ToolbarItems>
in your view moodel.
public MyViewModel()
{
CancelCommand = new AsyncCommand(ExecuteCancel);
}
public AsyncCommand CancelCommand {get;}
async Task ExecuteCancel()
{
await Navigation.PopModalAsync();
}
Here is a more complex version that disables the cancel option unless the Done option is currently running.
<ContentPage.ToolbarItems>
<ToolbarItem Text = "Done" Command="{Binding DoneCommand}" />
<ToolbarItem Text = "Cancel" Command="{Binding CancelCommand}" Priority="1" />
</ContentPage.ToolbarItems>
in your view moodel.
public MyViewModel()
{
DoneCommand = new AsyncCommand(ExecuteDone);
CancelCommand = new CustomAsyncCommand(ExecuteCancel, CanExecuteCancel);
PropertyChangedEventManager.AddHandler(DoneCommand, (sender, e) => CancelCommand.OnCanExecuteChanged(), nameof(DoneCommand.IsExecuting));
PropertyChangedEventManager.AddHandler(CancelCommand, (sender, e) => CancelCommand.OnCanExecuteChanged(), nameof(CancelCommand.IsExecuting));
}
private bool CanExecuteCancel()
{
return DoneCommand.IsExecuting && !CancelCommand.IsExecuting;
}
public AsyncCommand DoneCommand { get; }
public CustomAsyncCommand CancelCommand { get; }
async Task ExecuteDone()
{
await ... //Do stuff
}
async Task ExecuteCancel()
{
await Navigation.PopModalAsync();
}