Главное окно исчезает за окнами других приложений после того, как в дополнительном окне используется ShowDialog в третьем окне
Я заметил это очень странное поведение в приложении WPF.
У меня есть MainWindow
, который показан с помощью Show()
из App.OnStartup
. Сказанный MainWindow
может открыть (немодальный) SubWindow
, также используя Show()
. SubWindow
Owner
установлен на MainWindow
.
Когда SubWindow
закрыто, MainWindow
снова отображается (хорошо).
Некоторые действия могут привести к тому, что SubWindow
откроет третье окно в виде модального диалога, используя ShowDialog()
(Owner
установлено значение SubWindow
). Когда этот модальный диалог открывается и закрывается хотя бы один раз за время жизни SubWindow
, тогда возникает странная вещь.
После закрытия SubWindow
, MainWindow
не появляется. Вместо этого появляется какое-либо случайное окно за MainWindow
. Может ли кто-нибудь объяснить мне, почему это происходит, и как его исправить?
Не имеет значения, отображается ли модальное диалоговое окно с нормальным Window
, используя ShowDialog()
, или окно сообщения, показанное с помощью MessageBox.Show()
.
Вот некоторые минимальные коды, чтобы воспроизвести это. Создайте новое приложение WPF в visual studio и вставьте его в предварительно сгенерированный файл MainWindow.xaml.cs
Затем нажмите клавишу на клавиатуре, чтобы открыть только одно окно, закрыть его, как и следовало ожидать. Нажмите две клавиши, закройте оба, затем самое первое окно находится за Visual Studio (предположительно).
public MainWindow()
{
InitializeComponent();
this.PreviewKeyDown += (sender, e) =>
{
if (this.Owner is MainWindow)
{
// we're the SubWindow
MessageBox.Show("I am a modal dialog");
// code below produces the exact same behavior as the message box
//var dialog = new MainWindow();
//dialog.Owner = this;
//dialog.ShowDialog();
}
else
{
// we're the initial MainWindow created by App.
var subWindow = new MainWindow();
subWindow.Owner = this;
subWindow.Show();
}
};
}
Ответы
Ответ 1
Это довольно неприятная ошибка WPF, я никогда не обнаружил недостатка в коде, который ее вызывает, но там есть heckofalot комментариев "Gotta this this" в исходном коде, который посвящен фокусировке. Просто обходной путь, менее идеальный, вы можете решить его, явно отдав предпочтение владельцу при закрытии окна. Скопируйте/вставьте этот код в свой класс SubWindow;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) {
base.OnClosing(e);
if (!e.Cancel && this.Owner != null) this.Owner.Focus();
}
Ответ 2
Ударьте ту же проблему только при скрытии окна. Я не вижу, что в этой ситуации есть эквивалентное событие Closing, но в любом случае это работает:
if (Owner != null) Owner.Focus();
Hide();
Ответ 3
this.Owner.Focus(); не работает для меня, он все еще идет к окну позади, мне пришлось немного поиграться и попытаться использовать TopMost, проблема с TopMost заключается в том, что мне нужно было вернуть его в false после закрытия с ним. Я использовал как OnClosing, так и OnClosed событие.
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (!e.Cancel && this.Owner != null) this.Owner.TopMost = true;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (this.Owner != null)
{
this.Owner.TopMost = false;
}
}
Ответ 4
У меня была такая же проблема в WinFoms (.NET 4. 7+). Мой обходной путь - сначала закрыть первое диалоговое окно (вызвав его метод Close
), а затем показать второе диалоговое окно.
пример
- Основная форма открывает
FirstForm
-
FirstForm
открывает SecondForm
и вызывает проблему!
Временное решение
Вызовите метод Close
внутри FirstForm
который будет открывать SecondForm
:
// FirstForm.cs
using(var secondForm = new SecondForm())
{
Close(); // <- this closes FirstForm instance
secondForm.ShowDialog(owner: mainFormInstance);
}
НТН