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