在ShowDialog之后立即从ViewModel执行操作

时间:2016-04-02 17:55:07

标签: c# wpf mvvm async-await task

我有ViewModel这样:

public class WelcomeWindowVm : ViewModel
{
    private ViewModel view;

    public WelcomeWindowVm(){
        this.View = new LoginVm() { 
            Completed += (o, e) => {
                this.View = new OtherVm(e.User){ 
                    Completed += (o, e) =>; // and so on
                } 
            }
        };
    }

    public ViewModel View {
        get {
            return this.view;
        }

        set {
            this.view = value;
            this.OnPropertyChanged(nameof(this.View));
        }
    }
}

LoginVm是另一个Viewmodel,当其上的命令完成时触发Completed事件(仅在使用正确的登录凭据时触发该事件)。 OtherVm是另一个vm,无论出于何种原因,它都会触发完成的事件。

我使用View渲染DataTemplate。例如:

<Window.Resources>   
   <DataTemplate DataType="vm:LoginVm">
         Textboes and buttons here
    </DataTemplate>
    <DataTemplate DataType="vm:OtherVm">
        ...
    </DataTemplate>
</Window.Resources>
<ContentControl Content={Binding View} />

此窗口的DataContext在WelcomeWindowVm之前设置为ShowDialog级。

这很有效。使用ShowDialog显示窗口时,会显示LoginVm。然后在完成LoginVm的任何任务时OtherVm,依此类推。

现在我想把Completion的东西转换成Async / await模式。 LoginVm现在看起来像这样:

public LoginVm{
    ...
    private TaskCompletionSource<User> taskCompletionSource = new TaskCompletionSource<User>();
    ...
    // This is the Relay command handler
    public async void Login()
    {
        // Code to check if credentials are correct
        this.taskCompletionSource.SetResult(this.user);
        // ...
    }

    public Task<User> Completion(){
        return this.taskCompletionSource.Task;
    }
}

而不是:

public LoginVm{
    public event EventHandler<CustomArgs> Completed;

    // This is the Relay command handler
    public async void Login()
    {
        // Code to check if credentials are correct
        OnCompleted(this.user);
        // ...
    }
}

所以我可以像这样使用它:

public WelcomeWindowVm(){
    var loginVm = new LoginVm();
    this.View = new LoginVm();
    User user = await loginVm.Completion();

    var otherVm = new OtherVm(user);
    this.View = otherVm;
    Whatever wev = await otherVm.Completion();

    //And so on
}

但是我不能在构造函数中使用await,即使我使用异步方法,在调用ShowDialog之后如何在ShowDialog阻止之后在另一个类中调用它?< / p>

我认为使用async void会有效。但是从我所听到的情况来看,除非我在事件处理程序中使用它,否则应该避免使用它。

也许使用async Task方法而不是await方法?

1 个答案:

答案 0 :(得分:1)

你可以这样做:

    public WelcomeWindowVm() {
        var loginVm = new LoginVm();
        this.View = loginVm;
        loginVm.Completion().ContinueWith(loginCompleted =>
        {
            var otherVm = new OtherVm(loginCompleted.Result);
            this.View = otherVm;
            otherVm.Completion().ContinueWith(whateverCompleted =>
            {

            });
        });
    }