2016-04-02 10 views
1

ich ViewModel wie diese:eine Aktion von Ansichtsmodell Hat direkt nach dem Showdialog

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 ist ein weiteres Ansichtsmodell, deren Completed-Ereignis ausgelöst wird, wenn ein Befehl auf sie abgeschlossen ist (Das Ereignis wird nur dann ausgelöst, wenn die richtige Login Anmeldeinformationen verwendet werden). OtherVm ist eine weitere VM, deren abgeschlossenes Ereignis aus welchem ​​Grund auch immer ausgelöst wird.

Ich render die View mit einem DataTemplate. Zum Beispiel:

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

Die Datacontext dieses Fensters oben WelcomeWindowVm Klasse festgelegt ist, bevor ShowDialog.

Das funktioniert gut. Wenn das Fenster mit ShowDialog angezeigt wird, wird LoginVm angezeigt. Dann OtherVm, wenn die Aufgabe von LoginVm abgeschlossen ist, und so weiter.

Jetzt dachte ich daran, die Completion Zeug zu Async/erwarten Muster zu konvertieren. Die LoginVm sieht nun wie folgt aus:

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; 
    } 
} 

Statt dessen:

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); 
     // ... 
    } 
} 

Damit ich es wie folgt verwenden:

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 
} 

Aber ich kann nicht erwarten in ein verwenden Konstruktor und selbst wenn ich eine asynchrone Methode dafür verwende, wie werde ich sie in einer anderen Klasse aufrufen, nachdem ich ShowDialog seit ShowDialog Blöcke aufgerufen habe?

Ich denke, mit einer async void wird funktionieren. Aber von dem, was ich gehört habe, sollte es vermieden werden, es sei denn, ich benutze es in einem Event-Handler.

Verwenden Sie vielleicht eine async Task Methode aber nicht await es?

Antwort

1

Sie können es wie folgt tun:

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 => 
      { 

      }); 
     }); 
    } 
+0

Danke, wie man in einem Asynchron-Task-Methode setzen und warten, nicht wahr? Ich bin nicht vertraut mit benutzerdefinierten Aufgaben wie diesem. Also bin ich neugierig. –

+0

Nun sollten Sie sicherstellen, dass Ausnahmen nicht innerhalb dieser Methode ausgelöst werden können. Das Ignorieren von Warten wird normalerweise nicht empfohlen, da die darin enthaltenen Ausnahmen möglicherweise unbeobachtet bleiben. Wenn Sie dies berücksichtigen, dann ist es in Ordnung (obwohl ich persönlich die Methode oben bevorzuge). – Evk

+0

Gibt es eine Möglichkeit zu tun, was Sie getan haben, ohne ContinueWith zu verwenden? Async nur warten? –

Verwandte Themen