WPF所有者窗口置于子窗口之上

11

当你点击Owner window时,它在Child window下方,那么在WPF中是否可能让Owner window处于Child window之上?

以下是我调用Child window的示例:

Window2 window = new Window2();
window.Owner = this;
window.Show();

父/所有者窗口将始终位于子窗口下方。


1
你能详细说明一下你想要实现什么吗?我还是有点难以理解你希望窗口如何运作。谢谢! - Mark Carpenter
1
假设我们有Window1和Window2。 Window1被设置为Window2的所有者(代码在Window1的上下文中运行,“this”是Window1)。 当Window2位于Window1的顶部(在z轴上,因此被拖动),Window1将始终位于Window2下方。 所以我的问题是:是否可能使Window1位于Window2的上方/顶部,如何实现? - Andrija
1
我能够得到的唯一解决方案是不使Window1成为Window2的所有者,然而,它仍有问题。Window2将出现在Window1下方。 - Carlo
1
我需要类似的东西。我需要我的主窗口跟踪所有打开的子窗口,并且一旦用户单击任何一个窗口,我希望该窗口成为最顶部的窗口。这是你需要实现的吗?据我所知,所有者始终在拥有的窗口后面,你无法改变这一点。唯一的方法是自己跟踪子窗口。 - Stefan Vasiljevic
5个回答

7
为了获得您想要的行为,您不需要在任何一个窗口上设置所有者。
当关闭其中一个窗口以关闭您的虚拟“子”窗口时,您必须自己处理逻辑。
可能还需要实现与最小化、最大化等相关的其他逻辑。

2
这个页面上的许多答案都涉及将System.Windows.Application中的一些或所有(非-MainWindow)窗口的Window.Owner属性设置为null。虽然这是一个简单易行的解决方法,确实可以独立解决Window重叠问题,但不幸的是,它也抑制了许多有用的应用程序级功能,在以下领域中,WPF似乎还想提供:

  • Application的激活/停用(通过鼠标单击、桌面Alt-Tab切换等方式),
  • 正确遵守Application.​ShutdownMode属性,以及通常情况下,
  • 在关闭时有序清理、释放资源和退出您的Application

可以通过将一个特殊的不可见窗口实例指定为Application.MainWindow来解决Window重叠问题,同时仍保留这些系统范围的WPF功能。

修改应用程序,使其创建的第一个Window(分配给Application.MainWindowWindow)是一个特殊的虚拟Window,然后通过将其Visibility设置为Visibility.Hidden或调用Window.Hide()来使其不可见。这不会隐藏它所拥有的窗口。然后,确保您想要的包含真实内容的“主”窗口以及所有其他窗口都由此不可见窗口拥有。

一旦隐藏,虚拟Window将不会显示在Windows 10任务栏中。您可以在任何需要模拟特殊指定的可见窗口上设置Window.ShowInTaskbar属性,如有必要。

这种方法允许您的Application中的任何可见窗口位于其他窗口的顶部,同时仍保留WPF功能和系统级应用程序激活行为。例如,当Application被激活(通过单击任何一个窗口或通过Alt-tab),所有应用程序的窗口都会在任何其他桌面应用程序窗口之上一起出现,同时仍保留最近的“应用内”Z顺序。 WPF关闭功能也得到保留,包括正确观察根据关闭不可见MainWindow(或所有其他窗口)的Application.ShutdownMode逻辑。


2

我遇到了类似的情况。我解决这个问题的方法是在显示窗口后简单地移除所有者。

Window2 window = new Window2();
window.Owner = this;
window.Show();
window.Owner = null;

编辑: 有人回复了这个问题,当我看到它时,决定编写一个扩展方法。

public static void ShowAsIfChildOf(this Window childWindow, Window parentWindow)
{
  childWindow.Owner = parentWindow;
  childWindow.Show();
  childWindow.Owner = null;
}

简单而有效。 - Alexandru Dicu

0
请注意,Licht提到的解决方案。
Window2 window = new Window2();
window.Owner = this;
window.Show();
window.Owner = null;

在我看来,似乎与...相同

Window2 window = new Window2();
window.Show();

即使没有设置所有权关系,例如关闭所有者窗口时,所拥有的窗口不关闭等,可能并不是希望具备所有属性(除“所有者窗口永远不能覆盖所有的窗口”之外)的解决方案。
一旦建立了此关系,将出现以下行为: - 如果最小化了所有者窗口,则其所有的拥有窗口也会被最小化。 - 如果以一个拥有窗口最小化,它的所有者就不会最小化。 - 如果所有者窗口最大化,所有者窗口和其拥有的窗口都会被恢复。 - 所有者窗口永远不能覆盖某个拥有的窗口。 - 没有使用ShowDialog打开的拥有窗口不是模态的。用户仍然可以与所有者窗口交互。 - 如果关闭所有者窗口,则其所有的拥有窗口也会被关闭。
在我看来,最好的解决方案是Glenn Slayden在下面链接中描述的“隐藏主虚拟窗口”,尽管如果有更简单的方法就更好了。

https://dev59.com/n3NA5IYBdhLWcg3wL6yx#66110288


0

不要为子窗口设置Owner,然后在MainWindow中处理OnClosing事件,像这样:

private void MainWindow_OnClosing(object? sender, CancelEventArgs e)
{
    foreach (var window in Application.Current.Windows)
    {
        if (window is Window appWindow)
        {
            if(appWindow.Equals(Application.Current.MainWindow))
                continue;

            appWindow.Close();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接