Async command execution in MVVM light
Asked Answered
I

2

7

I am wondering why MVVM light is missing command with async execution? I believe there are many cases where this could be useful, so let me name one.

Let's say that our UI contains one container that contains multiple screens. User can close a particular screen or a container with multiple screens. Let's say that a user has issued a close command on the container. Container in return invokes close command on each screen, and it needs to wait for screen to be closed. This in practice can means validating data. saving, etc. For this reason we need to issue an async call to keep the UI from becoming unresponsive, and also we need to wait for 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 could also expose additional method on screen, but in my opinion it should be task of RelayCommand, since it already exist there.

Or there is a different methodology to handle such scenario?

Infest answered 30/12, 2014 at 3:26 Comment(0)
C
5

Probably because there are many different ways of doing it; I describe a few approaches in my MSDN article on the subject.

Asynchronous lifetime commands are especially tricky. Something like a "close" command must be carefully considered. Is there some indication that a close is in progress? What happens if the user closes more than once ("close" in particular can often be initiated by an OS or another app even if a "close button" is disabled)?

Caliber answered 30/12, 2014 at 4:20 Comment(3)
Does this use MVVM Light?Agricola
I cannot see how I'd apply it to MVVM Light, specifically how to load data from file (i.e. an inevitably asynchrous job) within the view model's constructor so that pages are Blendable. I'll keep thinking.Agricola
@dumbledad: It should work fine with MVVM Light or any other framework. The problem you're having is that you need it Blendable, and I'm not aware of the limitations that puts on it.Caliber
H
-1

I found this being in some ways a solution to making async commands in MVVM Light. If fact it overwrap a async method with Task.Run. Our wrapped method has to verify if it not executed twice, and catches errors from lower async 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;
            });
        }
    }
Hoyt answered 5/12, 2018 at 11:31 Comment(1)
You're really doing it wrong. Neither is using DispatcherHelper recommended, nor try/catch needed, nor even one of them suggested. I strongly suggest to you to read @Stephen Cleary's answer & comments above and/or watch at least youtu.be/J0mcYVxJEl0 on how to do stuff like this.Telfer

© 2022 - 2024 — McMap. All rights reserved.