Running Async Command in the Light of MVVM

I am wondering why the MVVM command passes light without asynchronous execution? I believe that there are many cases where this can be useful, so let me name it.

Suppose our user interface contains one container containing several screens. The user can close a specific screen or container with multiple screens. Suppose a user executes a close command in a container. The container, in turn, causes the command to close on each screen, and it needs to wait for the screen to close. This in practice can mean data verification. conservation, etc. For this reason, we need to issue an asynchronous call so that the user interface does not respond, and we also need to wait for the task to complete in order to continue.

So, if we have something like this in Command

public RelayCommand CloseCommand { get { return _closeCommand ?? _closeCommand = new RelayCommand( async () => { foreach (var screen in Screens) { if (!await screen.CloseCommand.ExecuteAsync(null)) { // do something } } }) } } 

We can also set an additional method on the screen, but, in my opinion, this should be the RelayCommand task, since it already exists.

Or is there another methodology for handling such a scenario?

+6
source share
2 answers

Probably because there are many different ways to do this; I describe several approaches in my MSDN article on this subject .

Asynchronous lifetime commands are especially complex. Something like a “closed” team should be carefully considered. Are there any signs that the closure is ongoing? What happens if a user closes more than once (for example, “close” can often be initiated by the OS or another application, even if the “close” button is disabled)?

+2
source

I found this in a way a solution for creating asynchronous commands in MVVM Light. If this fact wraps the asynchronous method with Task.Run. Our wrapped method should check to see if it executes twice, and catches errors due to lower asynchronous executions.

  private bool isLoading; public bool IsLoading { get { return isLoading; } set { if (value != isLoading) { Set(ref isLoading, value); //Used to refresh Commands CanExecute laying on IsLoading CommandManager.InvalidateRequerySuggested(); } } } private RelayCommand loadCommand; public RelayCommand LoadCommand { get { return loadCommand ?? (loadCommand = new RelayCommand( () => Task.Run(LoadAsync), () => !IsLoading )); } } private async Task LoadAsync() { //Prevents double execution in case of many mouse clicks on button if (IsLoading) { return; } //Assignments which need to be done on UI tread DispatcherHelper.CheckBeginInvokeOnUI(() => { IsLoading = true; }); try { list = await service.LoadAsync(); ... } catch (Exception e) { ... } finally { DispatcherHelper.CheckBeginInvokeOnUI(() => { IsLoading = false; }); } } 
0
source

Source: https://habr.com/ru/post/1210082/


All Articles