WPF модальное окно прогресса
Я прошу прощения, если на этот вопрос отвечали сотни раз, но я не могу найти ответ, который работает для меня. Я хотел бы создать модальное окно, которое показывает различные сообщения о прогрессе, в то время как мое приложение выполняет долго выполняющиеся задачи. Эти задачи выполняются в отдельном потоке, и я могу обновлять текст в окне прогресса на разных этапах процесса. Связь между потоками все работает хорошо. Проблема в том, что я не могу заставить окно быть поверх только других окон приложений (не всех приложений на компьютере), оставаться на вершине, предотвращать взаимодействие с родительским окном и все еще разрешать работу продолжать.
Вот что я пробовал до сих пор:
Во-первых, мое всплывающее окно - это пользовательский класс, который расширяет класс Window и имеет методы для обновления окна сообщения. Вначале я создаю новый экземпляр класса splash и показываю / скрываю его по мере необходимости.
В простейших случаях я создаю экземпляр окна и вызываю.Show()
в теме:
//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());
Это правильно отображает окно и продолжает выполнять мой код для обработки задач инициализации, но позволяет мне щелкнуть по родительскому окну и перенести его на передний план.
Затем я попытался отключить главное окно и включить его позже:
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));
Это отключает все элементы в окне, но я все еще могу щелкнуть главное окно и вывести его перед заставкой, а это не то, что мне нужно.
Затем я попытался использовать свойство topmost в всплывающем окне. Это держит его перед всем, и в сочетании с установкой свойства IsEnabled главного окна я мог бы предотвратить взаимодействие, но это заставляет экран-заставку появляться перед ВСЕМ, включая другие приложения. Я тоже этого не хочу. Я просто хочу, чтобы это было самое верхнее окно в ЭТОМ приложении.
Тогда я нашел сообщения об использовании.ShowDialog()
вместо.Show()
, Я попробовал это, и он правильно показал диалог и не позволил мне нажать на родительское окно, но вызывая.ShowDialog()
заставляет программу зависать, ожидая, пока вы закроете диалог, прежде чем она продолжит выполнение кода. Это, очевидно, тоже не то, что я хочу. Я полагаю, я мог бы позвонитьShowDialog()
в другом потоке, чтобы этот поток зависал, но поток, выполняющий работу, не ... это рекомендуемый метод?
Я также рассмотрел возможность вообще не использовать окно и вместо этого помещать полноразмерный элемент окна перед всем остальным на странице. Это будет работать за исключением того, что у меня есть другие окна, которые я открываю, и я хотел бы иметь возможность использовать заставку, когда они тоже открыты. Если бы я использовал элемент окна, мне пришлось бы заново создавать его в каждом окне, и я бы не смог использовать свой удобныйUpdateSplashText
метод в моем собственном классе заставки.
Так что это подводит меня к вопросу. Как правильно справиться с этим?
Спасибо за ваше время и извините за длинный вопрос, но детали важны :)