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?
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. –
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
Gibt es eine Möglichkeit zu tun, was Sie getan haben, ohne ContinueWith zu verwenden? Async nur warten? –