Okno postępu modalnego WPF

Przepraszam, jeśli na to pytanie padło wiele razy, ale nie mogę znaleźć odpowiedzi, która by mi odpowiadała. Chciałbym stworzyć modalne okno, które pokazuje różne komunikaty postępu, podczas gdy moja aplikacja wykonuje długie zadania. Te zadania są uruchamiane w osobnym wątku i jestem w stanie zaktualizować tekst w oknie postępu na różnych etapach procesu. Komunikacja między wątkami działa dobrze. Problem polega na tym, że nie mogę sprawić, by okno znajdowało się na wierzchu tylko innych okien aplikacji (nie każdej aplikacji na komputerze), pozostać na górze, uniemożliwić interakcję z oknem nadrzędnym i nadal pozwalać na kontynuowanie pracy.

Oto, co próbowałem do tej pory:

Po pierwsze, moje okno powitalne jest klasą niestandardową, która rozszerza klasę okna i ma metody aktualizacji okna wiadomości. Na początku tworzę nową instancję klasy splash i pokazuję / ukrywa ją w razie potrzeby.

W najprostszych przypadkach tworzę instancję okna i wywołuję.Show() na tym:

//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());

To poprawnie wyświetla okno i kontynuuje uruchamianie mojego kodu, aby obsłużyć zadania inicjalizacji, ale pozwala mi kliknąć okno nadrzędne i przenieść je na przód.

Następnie spróbowałem wyłączyć główne okno i włączyć je później:

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

Spowoduje to wyłączenie wszystkich elementów w oknie, ale nadal mogę kliknąć główne okno i przenieść je przed ekran powitalny, co nie jest tym, czego chcę.

Następnie spróbowałem użyć najwyższej właściwości w oknie powitalnym. Utrzymuje to przed wszystkim i w połączeniu z ustawieniem głównego okna właściwości IsEnabled mogę zapobiec interakcji, ale to sprawia, że ​​ekran powitalny pojawia się przed WSZYSTKIM, w tym innymi aplikacjami. Ja też tego nie chcę. Chcę tylko, aby było to najwyższe okno w tej aplikacji.

Potem znalazłem posty o używaniu.ShowDialog() zamiast.Show(). Próbowałem tego i poprawnie pokazał okno dialogowe i nie pozwolił mi na kliknięcie okna nadrzędnego, ale wywołanie.ShowDialog() sprawia, że ​​program zawiesza się, czekając na zamknięcie okna dialogowego, zanim będzie kontynuować uruchamianie kodu. To oczywiście nie to, czego chcę. Przypuszczam, że mógłbym zadzwonićShowDialog() na innym wątku, aby ten wątek się zawiesił, ale wątek wykonujący pracę nie ... czy jest to zalecana metoda?

Rozważałem również możliwość nieużywania okna w ogóle i zamiast tego umieszczania pełnowymiarowego elementu okna przed wszystkim innym na stronie. To zadziałałoby, z wyjątkiem tego, że mam inne otwarte okna i chciałbym móc korzystać z ekranu powitalnego, gdy te są również otwarte. Gdybym użył elementu okna, musiałbym go odtworzyć w każdym oknie i nie byłbym w stanie użyć mojego poręcznegoUpdateSplashText metoda w mojej niestandardowej klasie splash.

To prowadzi mnie do pytania. Jaki jest właściwy sposób radzenia sobie z tym?

Dziękuję za poświęcony czas i przepraszam za długie pytanie, ale szczegóły są ważne :)

questionAnswers(5)

yourAnswerToTheQuestion