WPF modales Fortschrittsfenster

8

Ich entschuldige mich, wenn diese Frage tonnenweise beantwortet wurde, aber ich kann keine Antwort finden, die für mich funktioniert. Ich möchte ein modales Fenster erstellen, das verschiedene Fortschrittsnachrichten anzeigt, während meine Anwendung lange laufende Aufgaben ausführt. Diese Aufgaben werden in einem separaten Thread ausgeführt und ich kann den Text im Fortschrittsfenster in verschiedenen Phasen des Prozesses aktualisieren. Die Cross-Thread-Kommunikation funktioniert alles gut. Das Problem ist, dass ich das Fenster nicht nur auf andere Anwendungsfenster (nicht auf jede Anwendung auf dem Computer) bringen kann, bleibe oben, verhindere die Interaktion mit dem Elternfenster und erlaube trotzdem, dass die Arbeit fortgesetzt wird.

Folgendes habe ich bisher versucht:

Zunächst 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 zeige / verstecke sie bei Bedarf.

Im einfachsten Fall instanziiere ich das Fenster und rufe .Show() darauf auf:

%Vor%

Dies zeigt das Fenster korrekt an und führt meinen Code weiter aus, um die Initialisierungsaufgaben zu bearbeiten, aber ich kann auf das übergeordnete Fenster klicken und es nach vorne bringen.

Als nächstes habe ich versucht, das Hauptfenster zu deaktivieren und später wieder zu aktivieren:

%Vor%

Dies deaktiviert alle Elemente im Fenster, aber ich kann immer noch auf das Hauptfenster klicken und es vor den Begrüßungsbildschirm bringen, was ich nicht möchte.

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 konnte ich die Interaktion verhindern, aber dadurch wird der Begrüßungsbildschirm vor ALLEN angezeigt, einschließlich anderer Anwendungen. Ich will das auch nicht. Ich möchte nur, dass es das oberste Fenster in dieser Anwendung ist.

Dann habe ich Posts über die Verwendung von .ShowDialog() anstelle von .Show() gefunden. Ich habe es versucht, und es zeigte den Dialog korrekt an und erlaubte mir nicht, auf das Elternfenster zu klicken, aber das Aufrufen von .ShowDialog() lässt das Programm hängen und wartet darauf, dass Sie das Dialogfeld schließen, bevor es weiter Code ausführt. Das ist offensichtlich nicht das, was ich auch will. Ich nehme an, ich könnte ShowDialog() in einem anderen Thread aufrufen, so dass dieser Thread hängen bleibt, aber der Thread, der die Arbeit erledigt, wäre nicht ... ist das die empfohlene Methode?

Ich habe auch die Möglichkeit in Erwägung gezogen, überhaupt kein Fenster zu verwenden und stattdessen ein Fensterelement voller Größe vor allem anderen auf der Seite zu platzieren. Das würde funktionieren, außer dass ich andere Fenster habe, die ich öffne, und ich würde gerne den Begrüßungsbildschirm verwenden können, 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 meine handliche UpdateSplashText -Methode nicht in meiner benutzerdefinierten Splash-Klasse verwenden.

Das bringt mich zu der Frage. Was ist der richtige Weg, damit umzugehen?

Vielen Dank für Ihre Zeit und Entschuldigung für die lange Frage, aber Details sind wichtig:)

    
BrianVPS 15.08.2013, 17:17
quelle

4 Antworten

13

Sie haben Recht, dass ShowDialog Ihnen den größten Teil des von Ihnen gewünschten Benutzeroberflächenverhaltens bietet.

Es hat das Problem, dass Sie die Ausführung sofort blockieren, sobald Sie es aufrufen. Wie könnten Sie möglicherweise Code ausführen, nachdem Sie das Formular angezeigt haben, aber definieren, was es sein soll, bevor es angezeigt wird? Das ist dein Problem.

Sie könnten einfach alle Arbeiten innerhalb der Sprinkler-Klasse erledigen, aber das ist wegen der engen Kopplung ziemlich schlecht.

Sie können das Loaded -Ereignis von Window nutzen, um Code zu definieren, der ausgeführt werden soll, nachdem das Fenster angezeigt wurde, aber wo es definiert ist, bevor Sie es anzeigen.

%Vor%

Beachten Sie, dass diese Methode den Codebeispielcode hier kapseln soll, sodass Sie jede Worker-Methode übergeben können, die den Fortschrittsanzeiger akzeptiert, und dies in einem Hintergrundthread ausführt, während ein generischer Begrüßungsbildschirm mit Fortschritt angezeigt wird vom Arbeiter.

Dies könnte dann etwa so heißen:

%Vor%     
Servy 15.08.2013 18:05
quelle
1

Sie können die Eigenschaft Visibility auf Window verwenden, um das gesamte Fenster auszublenden, während der Begrüßungsbildschirm ausgeführt wird.

XAML

%Vor%

Code

%Vor%     
Shoe 15.08.2013 17:47
quelle
1

Sie können den Konstruktor Ihres Fortschrittsfensters auf Task setzen und dann sicherstellen, dass das Fenster task.Start für das Ereignis OnLoaded aufruft. Dann verwenden Sie ShowDialog aus dem übergeordneten Formular, was dazu führt, dass das Fortschrittsfenster die Aufgabe startet.

Hinweis: Sie könnten auch task.Start im Konstruktor oder im übergeordneten Formular an einer beliebigen Stelle aufrufen, bevor Sie ShowDialog aufrufen. Was auch immer für Sie am sinnvollsten ist.

Eine andere Option wäre, nur einen Fortschrittsbalken in der Statusleiste des Hauptfensters zu verwenden und das Popup loszuwerden. Diese Option scheint heutzutage immer häufiger anzukommen.

    
Dax Fohl 15.08.2013 17:43
quelle
-1

Ich habe einen Weg gefunden, dies zu erreichen, indem ich ShowDialog() in einem separaten Thread anrufe. Ich habe meine eigenen Methoden ShowMe() und HideMe() in meiner Dialogklasse erstellt, die die Arbeit behandeln. Ich erfasse auch das Ereignis Closing , um zu verhindern, dass der Dialog geschlossen wird, damit ich ihn wiederverwenden kann.

Hier ist mein Code für meine Splash-Screen-Klasse:

%Vor%     
BrianVPS 15.08.2013 17:48
quelle

Tags und Links