wpf 子窗口在第三个窗口上使用 ShowDialog 后,主窗口消失在其他应用程序的窗口后面

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13209526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:03:54  来源:igfitidea点击:

Main window disappears behind other application's windows after a sub window uses ShowDialog on a third window

c#wpfdialogwindowmodal-dialog

提问by dialer

I have noticed this very odd behavior in a WPF application.

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

I have a MainWindow, which is shown using Show()from App.OnStartup. Said MainWindowcan open a (non-modal) SubWindow, also using Show(). SubWindow's Owneris set to MainWindow.

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

When SubWindowis closed, MainWindowis visible again (good).

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

Some actions can cause the SubWindowto open a third window as a modal dialog, using ShowDialog()(Owneris set to SubWindow). When that modal dialog is opened and closed at least once during the lifetime of a SubWindow, then the weird thing happens.

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

After closing SubWindow, MainWindowdoes not come into view. Instead, whatever random window is behindMainWindowcomes into view. Can anyone explain to me why this happens, and how to fix it?

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

It makes no difference whether the modal dialog is a normal Windowdisplayed using ShowDialog(), or a message box shown using MessageBox.Show().

模态对话框是正常Window显示的 usingShowDialog()还是显示的消息框都没有区别MessageBox.Show()



Here is some minimalcode to reproduce this. Create a new WPF application in visual studio, and paste this into the pre-generated MainWindow.xaml.cs

这是一些最小的代码来重现这一点。在visual studio中新建一个WPF应用,粘贴到预先生成的MainWindow.xaml.cs中

Then, press a key on the keyboard to open only one window, close it, behavior as expected. Press two keys, close both, then the very first window is behind Visual Studio (presumably).

然后,按键盘上的一个键只打开一个窗口,关闭它,行为如预期。按两个键,关闭两个键,然后第一个窗口在 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();
        }
    };
}

采纳答案by Hans Passant

This is a pretty annoying WPF bug, I never did find the flaw in the code that causes it but there's a heckofalot of "gotta figure this out" comments in the source code that deals with focusing. Just a workaround, a less than ideal one, you can solve it by explicitly giving the focus to the owner when the window is closing. Copy/paste this code in your SubWindow class;

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

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e) {
        base.OnClosing(e);
        if (!e.Cancel && this.Owner != null) this.Owner.Focus();
    }

回答by johndsamuels

Hit the same problem only with hiding the window. I can't see that there is an equivalent event to Closing in this situation, but anyway this works:

只有隐藏窗口才能遇到同样的问题。在这种情况下,我看不出有与 Closing 等效的事件,但无论如何这是有效的:

        if (Owner != null) Owner.Focus();
        Hide();

回答by Daren Delima

this.Owner.Focus(); is not working for me it still goes to the window behind I had to play around a bit much and tried to used TopMost, the problem with TopMost is I needed to return it to false after the close with it. I used both OnClosing and OnClosed event.

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;
    }
}

回答by Kamran

I had the same problem in WinFoms (.NET 4.7+). My workaround was closing the first dialog first (calling its Closemethod) and show the second dialog afterwards.

我在 WinFoms (.NET 4.7+) 中遇到了同样的问题。我的解决方法是先关闭第一个对话框(调用它的Close方法),然后显示第二个对话框。

Example

例子

  1. Main form opens FirstForm
  2. FirstFormopens SecondFormand causes the problem!
  1. 主窗体打开 FirstForm
  2. FirstForm打开SecondForm并导致问题!

Workaround

解决方法

Call Closemethod inside the FirstFormwhich will be going to open the SecondForm:

Close里面的调用方法FirstForm将打开SecondForm

// FirstForm.cs

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

HTH

HTH