Главное окно исчезает за окнами других приложений после того, как в дополнительном окне используется 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), а затем показать второе диалоговое окно.

пример

  1. Основная форма открывает FirstForm
  2. FirstForm открывает SecondForm и вызывает проблему!

Временное решение

Вызовите метод Close внутри FirstForm который будет открывать SecondForm:

// FirstForm.cs

using(var secondForm = new SecondForm())
{
    Close(); // <- this closes FirstForm instance
    secondForm.ShowDialog(owner: mainFormInstance);
}

НТН