I apologize if this question has been answered many times, but I canβt find an answer that works for me. I would like to create a modal window that shows various progress messages while my application performs lengthy tasks. These tasks are performed in a separate thread, and I can update the text in the execution window at different stages of the process. Communication between threads works well. The problem is that I cannot force the window to be on top of other application windows (not for every application on the computer), stay on top, prevent interaction with the parent window and still allow it to continue working.
Here is what I have tried so far:
Firstly, my popup is a custom class that extends the Window class and has methods for updating the message box. I create a new instance of the splash class at an early stage and show / hide it as needed.
In the simplest case, I instantiate a window and call .Show() on it:
//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());
This displays the window correctly and continues to run my code to handle initialization tasks, but allows me to click on the parent window and bring it to the foreground.
Next, I tried to turn off the main window and turn it back on later:
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));
This disables all the elements in the window, but I can still click on the main window and bring it before the splash screen, which is not what I want.
Then I tried to use the top property in the splash window. This holds it in front of everything, and in combination with setting the IsEnabled property of the main window, I can prevent interaction, but it causes a pop-up screen in front of EVERYTHING, including other applications. I donβt want that either. I just want this to be the topmost window in this application.
Then I found messages about using .ShowDialog() instead of .Show() . I tried this and it showed the dialog correctly and did not allow me to click on the parent window, but the .ShowDialog() call causes the program to hang until you close the dialog before it continues to execute the code. This is obviously not what I want. I suppose I could call ShowDialog() in another thread so that this thread hangs, but the thread doing the work is not ... is this the recommended method?
I also considered the option of not using the window at all and instead placing the full-sized window element in front of everything else on the page. This will work, except that I have other windows that I open, and I would like to be able to use the splash screen when they are open. If I used a window element, I would have to recreate it in each window, and I would not be able to use my convenient UpdateSplashText method in my custom splash class.
So that brings me to the question. What is the right way to handle this?
Thanks for your time and sorry for the long question, but the details are important :)