WPF modales Fortschrittsfenster
Ich entschuldige mich, wenn diese Frage unzählige Male beantwortet wurde, aber ich kann anscheinend keine Antwort finden, die für mich funktioniert. Ich möchte ein modales Fenster erstellen, in dem verschiedene Statusmeldungen angezeigt werden, während meine Anwendung Aufgaben ausführt, die lange ausgeführt werden. Diese Aufgaben werden in einem separaten Thread ausgeführt und ich kann den Text im Fortschrittsfenster in verschiedenen Phasen des Prozesses aktualisieren. Die fadenübergreifende Kommunikation funktioniert gut. Das Problem ist, dass das Fenster nicht nur über anderen Anwendungsfenstern angezeigt wird (nicht über jeder Anwendung auf dem Computer), dass ich im Vordergrund bleibe, die Interaktion mit dem übergeordneten Fenster verhindere und weiterhin zulasse, dass die Arbeit fortgesetzt wird.
Folgendes habe ich bisher versucht:
Erstens ist mein Begrüßungsfenster eine benutzerdefinierte Klasse, die die Window-Klasse erweitert und über Methoden zum Aktualisieren des Meldungsfelds verfügt. Ich erstelle frühzeitig eine neue Instanz der Splash-Klasse und blende sie nach Bedarf ein / aus.
Im einfachsten Fall instanziiere ich das Fenster und rufe auf.Show()
darauf:
//from inside my secondary thread
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Show());
//Do things
//update splash text
//Do more things
//close the splash when done
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Hide());
Dadurch wird das Fenster korrekt angezeigt und mein Code wird weiterhin ausgeführt, um die Initialisierungsaufgaben zu erledigen. Dadurch kann ich jedoch auf das übergeordnete Fenster klicken und es in den Vordergrund stellen.
Als nächstes habe ich versucht, das Hauptfenster zu deaktivieren und später wieder zu aktivieren:
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = false));
//show splash, do things, etc
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = true));
Dadurch werden alle Elemente im Fenster deaktiviert, aber ich kann trotzdem auf das Hauptfenster klicken und es vor den Begrüßungsbildschirm bringen, was nicht meine Absicht ist.
Als nächstes habe ich versucht, die oberste Eigenschaft im Begrüßungsfenster zu verwenden. Dies hält es vor allem und in Verbindung mit dem Festlegen der IsEnabled-Eigenschaft des Hauptfensters könnte ich die Interaktion verhindern, aber dadurch wird der Begrüßungsbildschirm vor ALLES angezeigt, einschließlich anderer Anwendungen. Das will ich auch nicht. Ich möchte nur, dass es das oberste Fenster in DIESER Anwendung ist.
Dann habe ich Beiträge über die Verwendung gefunden.ShowDialog()
anstatt.Show()
. Ich habe es versucht, und es zeigte den Dialog korrekt an und erlaubte mir nicht, auf das übergeordnete Fenster zu klicken, sondern anzurufen.ShowDialog()
Das Programm bleibt hängen und wartet darauf, dass Sie den Dialog schließen, bevor der Code weiter ausgeführt wird. Das will ich natürlich auch nicht. Ich nehme an, ich könnte anrufenShowDialog()
auf einem anderen Thread, so dass dieser Thread hängen würde, aber der Thread, der die Arbeit macht, würde nicht ... ist das die empfohlene Methode?
Ich habe auch die Möglichkeit in Betracht gezogen, überhaupt kein Fenster zu verwenden und stattdessen ein Fensterelement in voller Größe vor alles andere auf der Seite zu setzen. Dies würde funktionieren, außer dass ich andere Fenster habe, die ich öffne, und den Begrüßungsbildschirm verwenden möchte, wenn diese auch geöffnet sind. Wenn ich ein Fensterelement verwenden würde, müsste ich es in jedem Fenster neu erstellen, und ich könnte mein Handy nicht verwendenUpdateSplashText
Methode in meiner benutzerdefinierten Splash-Klasse.
Das bringt mich zu der Frage. Was ist der richtige Weg, um damit umzugehen?
Vielen Dank für Ihre Zeit und Entschuldigung für die lange Frage, aber Details sind wichtig :)