为什么关闭最后一个子窗口会使其父窗口最小化?

时间:2022-09-07 00:25:52

I have the following simple wpf application:

我有以下简单的wpf应用程序:

App.xaml:

App.xaml中:

<Application x:Class="TestWpf2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>

App.xaml.cs:

App.xaml.cs:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var parentWindow = new Window();
        parentWindow.Show();

        var childWindow1 = new Window { Owner = parentWindow };
        childWindow1.Show();

        var childWindow2 = new Window { Owner = parentWindow };
        childWindow2.Show();
    }
}

The application causes 3 windows to appear on screen. If you run the application and close the two child windows, the parent window is minimized to the task bar. If you comment out childWindow2.show(), run the application, and close the single child window, the parent window is not minimized to the taskbar.

该应用程序导致3个窗口出现在屏幕上。如果运行应用程序并关闭两个子窗口,父窗口将最小化到任务栏。如果注释掉childWindow2.show(),运行应用程序,并关闭单个子窗口,则父窗口不会最小化到任务栏。

I can add the following code to work around this problem:

我可以添加以下代码来解决此问题:

childWindow1.Closing += delegate(object sender, CancelEventArgs ex)
{
    (sender as Window).Owner = null;
};

but I don't want to use a hack like this, and I want to understand why this problem occurs.

但我不想使用这样的黑客,我想知道为什么会出现这个问题。

Why does this happen?

为什么会这样?

3 个解决方案

#1


15  

This is a WPF undocumented feature(Bug)

这是一个WPF未记录的功能(Bug)

This bug has been reported to Microsoft more than 7 years ago.

这个错误已经在7年多前向微软报告过了。

Modal dialog on top of non-modal window sends main window to back.

非模态窗口顶部的模态对话框将主窗口发送回去。

The WPF team has recently reviewed this issue and will not be addressing this issue as at this time the team is focusing on the bugs impacting the highest number of WPF developers.

WPF团队最近审查了这个问题,并且不会解决这个问题,因为此时团队正在关注影响最多WPF开发人员的bug。

Let's look at the behavior of this undocumented feature a bit.

让我们看一下这个未记录的功能的行为。

It doesn't Minimize, just go one window behind (in debug mode, behind the visual studio window)

它没有最小化,只是在后面的一个窗口(在调试模式下,在visual studio窗口后面)

Steps to prove:

证明的步骤:

  • Run this application.

    运行此应用程序。

  • Minimize all other windows (eg: visual studio and all other windows). Keep only these three windows on the screen.

    最小化所有其他窗口(例如:visual studio和所有其他窗口)。只在屏幕上保留这三个窗口。

  • Close both children, parent is still in Normal State

    关闭两个孩子,父母仍处于正常状态

Test this code for further proof: StateChange wouldn't fire.

测试此代码以获得进一步证明:StateChange不会触发。

        protected override void OnStartup(StartupEventArgs e)
        {
            var parentWindow = new Window() { Title = "Parent" };
            parentWindow.StateChanged += (sender, ep)=>
            {
                var state = ((Window)sender).WindowState;
            };
            parentWindow.Show();

            var childWindow1 = new Window { Owner = parentWindow, Title = "Child1" };
            childWindow1.Show();

            var childWindow2 = new Window { Owner = parentWindow, Title = "Child2" };
            childWindow2.Show();
        }

Being TopMost prevent this happening

成为TopMost可以防止这种情况发生

If parent window is TopMost, this wouldn't happen. But this may not be an option in many cases.

如果父窗口是TopMost,则不会发生这种情况。但在许多情况下,这可能不是一种选择。

parentWindow.Topmost = true;

Workaround

解决方法

Activate the parent on child2 close.

在child2关闭时激活父级。

childWindow2.Closed += (a, b) => { parentWindow.Activate(); };

#2


3  

This is due to the fact that you can't use the parent window once the child window is shown with the Owner set. Just try to access the parent window while the child is on the screen, and it won't let you, to see what i mean.

这是因为在使用所有者设置显示子窗口后,您无法使用父窗口。只是在孩子在屏幕上时尝试访问父窗口,它不会让你看到我的意思。

If you don't specify Owner then this behaviour doesn't happen.

如果您未指定所有者,则不会发生此行为。

#3


1  

I never worked out what is causing this to happen! In the end, I wrote this code that is called after any child window is closed:

我从来没有弄清楚导致这种情况发生的原因!最后,我编写了在关闭任何子窗口后调用的代码:

// App inherits from Application, and has a Window property called MainWindow
// and a List<Window> property called OpenWindows.
if (!App.OpenWindows.Any())
    App.ParentWindow.Activate();

So if the last child window is closed (making App.OpenWindows.Any() false) the parent window is activated. This does not result in flicker (the main window minimizing then maximizing, for instance.)

因此,如果最后一个子窗口关闭(使App.OpenWindows.Any()为false),则会激活父窗口。这不会导致闪烁(主窗口最小化,然后最大化,例如)。

This isn't the best solution. I will not close this question in the hope that someone can explain why WPF has this functionality!

这不是最好的解决方案。我不会关闭这个问题,希望有人能解释为什么WPF有这个功能!

#1


15  

This is a WPF undocumented feature(Bug)

这是一个WPF未记录的功能(Bug)

This bug has been reported to Microsoft more than 7 years ago.

这个错误已经在7年多前向微软报告过了。

Modal dialog on top of non-modal window sends main window to back.

非模态窗口顶部的模态对话框将主窗口发送回去。

The WPF team has recently reviewed this issue and will not be addressing this issue as at this time the team is focusing on the bugs impacting the highest number of WPF developers.

WPF团队最近审查了这个问题,并且不会解决这个问题,因为此时团队正在关注影响最多WPF开发人员的bug。

Let's look at the behavior of this undocumented feature a bit.

让我们看一下这个未记录的功能的行为。

It doesn't Minimize, just go one window behind (in debug mode, behind the visual studio window)

它没有最小化,只是在后面的一个窗口(在调试模式下,在visual studio窗口后面)

Steps to prove:

证明的步骤:

  • Run this application.

    运行此应用程序。

  • Minimize all other windows (eg: visual studio and all other windows). Keep only these three windows on the screen.

    最小化所有其他窗口(例如:visual studio和所有其他窗口)。只在屏幕上保留这三个窗口。

  • Close both children, parent is still in Normal State

    关闭两个孩子,父母仍处于正常状态

Test this code for further proof: StateChange wouldn't fire.

测试此代码以获得进一步证明:StateChange不会触发。

        protected override void OnStartup(StartupEventArgs e)
        {
            var parentWindow = new Window() { Title = "Parent" };
            parentWindow.StateChanged += (sender, ep)=>
            {
                var state = ((Window)sender).WindowState;
            };
            parentWindow.Show();

            var childWindow1 = new Window { Owner = parentWindow, Title = "Child1" };
            childWindow1.Show();

            var childWindow2 = new Window { Owner = parentWindow, Title = "Child2" };
            childWindow2.Show();
        }

Being TopMost prevent this happening

成为TopMost可以防止这种情况发生

If parent window is TopMost, this wouldn't happen. But this may not be an option in many cases.

如果父窗口是TopMost,则不会发生这种情况。但在许多情况下,这可能不是一种选择。

parentWindow.Topmost = true;

Workaround

解决方法

Activate the parent on child2 close.

在child2关闭时激活父级。

childWindow2.Closed += (a, b) => { parentWindow.Activate(); };

#2


3  

This is due to the fact that you can't use the parent window once the child window is shown with the Owner set. Just try to access the parent window while the child is on the screen, and it won't let you, to see what i mean.

这是因为在使用所有者设置显示子窗口后,您无法使用父窗口。只是在孩子在屏幕上时尝试访问父窗口,它不会让你看到我的意思。

If you don't specify Owner then this behaviour doesn't happen.

如果您未指定所有者,则不会发生此行为。

#3


1  

I never worked out what is causing this to happen! In the end, I wrote this code that is called after any child window is closed:

我从来没有弄清楚导致这种情况发生的原因!最后,我编写了在关闭任何子窗口后调用的代码:

// App inherits from Application, and has a Window property called MainWindow
// and a List<Window> property called OpenWindows.
if (!App.OpenWindows.Any())
    App.ParentWindow.Activate();

So if the last child window is closed (making App.OpenWindows.Any() false) the parent window is activated. This does not result in flicker (the main window minimizing then maximizing, for instance.)

因此,如果最后一个子窗口关闭(使App.OpenWindows.Any()为false),则会激活父窗口。这不会导致闪烁(主窗口最小化,然后最大化,例如)。

This isn't the best solution. I will not close this question in the hope that someone can explain why WPF has this functionality!

这不是最好的解决方案。我不会关闭这个问题,希望有人能解释为什么WPF有这个功能!