16

我在 WPF 应用程序中注意到了这种非常奇怪的行为。

我有一个MainWindow,使用Show()from显示App.OnStartup。说MainWindow可以打开一个(非模态)SubWindow,也可以使用Show()SubWindowOwner设置为MainWindow

SubWindow关闭时,再次MainWindow可见(好)。

某些操作可能会导致SubWindow打开第三个窗口作为模式对话框,使用ShowDialog()(Owner设置为SubWindow)。当该模态对话框在 a 的生命周期中至少打开和关闭一次时SubWindow,就会发生奇怪的事情。

关闭后SubWindowMainWindow不会出现。相反,无论后面 是什么随机窗口MainWindow都会进入视野。谁能向我解释为什么会发生这种情况,以及如何解决?

模态对话框是使用 显示的普通对话框WindowShowDialog()还是使用 显示的消息框没有区别MessageBox.Show()


这是一些重现此的最小代码。在 Visual Studio 中创建一个新的 WPF 应用程序,并将其粘贴到预先生成的 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();
        }
    };
}
4

5 回答 5

13

这是一个非常烦人的 WPF 错误,我从未在代码中找到导致它的缺陷,但在处理聚焦的源代码中存在大量“必须弄清楚”的注释。只是一种解决方法,一种不太理想的解决方法,您可以通过在窗口关闭时将焦点明确地赋予所有者来解决它。将此代码复制/粘贴到您的 SubWindow 类中;

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e) {
        base.OnClosing(e);
        if (!e.Cancel && this.Owner != null) this.Owner.Focus();
    }
于 2012-11-03T14:16:05.740 回答
0

仅在隐藏窗口时遇到相同的问题。在这种情况下,我看不到有与 Closing 等效的事件,但无论如何这有效:

        if (Owner != null) Owner.Focus();
        Hide();
于 2013-06-26T15:43:24.653 回答
0

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;
    }
}
于 2018-04-20T19:57:17.837 回答
0

我在 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);
}

高温高压

于 2019-06-17T05:02:32.183 回答
0

老问题,但我想我会分享对我的 C# WinForms 应用程序有用的东西,因为 Owner.Focus() 对我不起作用。

这是 Daren 的 TopMost 修复的一个变体,但我发现我实际上不必将 TopMost 设置为 true 并返回。只需将其设置为自身就可以防止父窗口消失在其他应用程序后面。

protected override void OnClosing(CancelEventArgs e) {
    if (Owner != null)
        Owner.TopMost = Owner.TopMost;
    base.OnClosing(e);
}
于 2020-07-10T21:26:06.230 回答