wpf 模态对话框未显示在其他窗口之上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6417558/
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-08 22:55:09  来源:igfitidea点击:

Modal Dialog not showing on top of other windows

wpfshowdialog

提问by Pratz

I am using Window.ShowDialog()to open a modal window in my WPF (MVVM) application, but it lets me navigate to other windows using the Windows taskbar (Windows 7).

我正在使用Window.ShowDialog()在我的 WPF (MVVM) 应用程序中打开一个模式窗口,但它允许我使用 Windows 任务栏 (Windows 7) 导航到其他窗口。

Consider this: I have 3 non-modal windows open in my application. Now One of these opens a modal window using Window.ShowDialog(). I also set Application.MainWindowas the owner of the modal window. This is so because I am using MVVM messaging and the message handler to open a new window is centralized in App.xaml.cs. The window does opens modally - no issues there. However, Windows 7 allows me to swtich to the other application windows from the taskbar. This leads to a situation where the modal window goes behind another window, which I prefer not to have.

考虑一下:我的应用程序中打开了 3 个非模态窗口。现在其中之一使用Window.ShowDialog(). 我还设置Application.MainWindow为模态窗口的所有者。这是因为我使用 MVVM 消息传递,并且打开新窗口的消息处理程序集中在App.xaml.cs. 窗口确实以模态打开 - 没有问题。但是,Windows 7 允许我从任务栏切换到其他应用程序窗口。这会导致模态窗口位于另一个窗口后面的情况,我不想这样做。

I can't do anything on other windows as long as I have the modal open, but it would be nice if the modal window always remained on top as long as it's open. Is there a way I can disable taskbar switching when the modal is open? FYI - all open windows launched from the app appear as separate entries on the taskbar.

只要我打开模态窗口,我就不能在其他窗口上做任何事情,但是如果模态窗口在打开时始终保持在顶部,那就太好了。有没有办法在模式打开时禁用任务栏切换?仅供参考 - 从应用程序启动的所有打开的窗口在任务栏上都显示为单独的条目。

Thanks in advance!

提前致谢!

回答by user7116

There isn't any code to base this off of, but it sounds like you have left off some properties on the Windowyou've created and expected ShowDialogto apply additional "dialog" semantics:

没有任何代码可以以此为基础,但听起来您已经在Window您创建的对象上遗漏了一些属性,并希望ShowDialog应用额外的“对话”语义:

Window window = new Window()
{
    Title = "Modal Dialog",
    ShowInTaskbar = false,               // don't show the dialog on the taskbar
    Topmost = true,                      // ensure we're Always On Top
    ResizeMode = ResizeMode.NoResize,    // remove excess caption bar buttons
    Owner = Application.Current.MainWindow,
};

window.ShowDialog();

回答by koalix

Setting Topmost to True (Topmost=True) causes the dialog to be on the top of all windows in the system (not only in application).

将 Topmost 设置为 True (Topmost=True) 会导致对话框位于系统中所有窗口的顶部(不仅在应用程序中)。

So you can try to register the event Activated in your main window:

因此,您可以尝试在主窗口中注册 Activated 事件:

Activated += WindowActivated;

and activate an owner window of the modal dialog every time when another main window of your application become active.

并在每次应用程序的另一个主窗口变为活动状态时激活模态对话框的所有者窗口。

private void WindowActivated(object sender, EventArgs e)
{
    Window window = Application.Current.Windows.OfType<YourMainWindow>().FirstOrDefault(p => p != this && !p.IsActive && p.OwnedWindows.Count > 0);
    if (window != null)
    {
        window.Activate();
    }
}

This simple hack assumes all your children windows are modal, but you can write a more sophisticated logic.

这个简单的 hack 假设您所有的子窗口都是模态的,但是您可以编写更复杂的逻辑。

回答by Bitbauer

Just set the owner property of the Window to the calling window. Then the activation of the WPF application in taskbar not just activates the MainWindow but also the modal child window and brings it to the front.

只需将 Window 的 owner 属性设置为调用窗口即可。然后在任务栏中激活 WPF 应用程序不仅激活 MainWindow 还激活模态子窗口并将其带到前面。

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();

回答by GrandMasterFlush

I ended up using a combination of a couple of the answers here. The accepted answer was useful at first but as other people on here have pointed out setting Topmost = truemeans that the window is always above any other applications running. My solution was this:

我最终在这里使用了几个答案的组合。接受的答案起初很有用,但正如这里的其他人指出的那样,设置Topmost = true意味着该窗口始终高于正在运行的任何其他应用程序。我的解决方案是这样的:

var myWindow = new MyWindowType();
myWindow.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);

I initially used:

我最初使用:

myWindow.Owner = Application.Current.MainWindow;

However, this method causes problems if you have three windows open like this:

但是,如果您像这样打开三个窗口,则此方法会导致问题:

MainWindow
   |
   -----> ChildWindow1

               |
               ----->  ChildWindow2

Then setting ChildWindow2.Owner = Application.Current.MainWindowwill set the owner of the window to be its grandparent window, not parent window.

然后设置ChildWindow2.Owner = Application.Current.MainWindow会将窗口的所有者设置为其祖父窗口,而不是父窗口。

To speed things up, I've added it as a code snippet in Visual Studio. If you add the following to Tools --> Code Snippet Manager --> My Code Snippets:

为了加快速度,我已将其添加为 Visual Studio 中的代码片段。如果将以下内容添加到工具 --> 代码片段管理器 --> 我的代码片段:

<CodeSnippets
    xmlns="http://schemas.microsoft.com/VisualStudio/2010/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>MVVM Set owner of page to be current active window</Title>
      <Shortcut>owner</Shortcut>
    </Header>
    <Snippet>
      <Code Language="CSharp">
        <![CDATA[System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Typing 'owner' and double-tapping the tab key will add the 'Application.CurrentWindows...' part in for you automatically.

输入“所有者”并双击 Tab 键将Application.CurrentWindows...自动为您添加“ ”部分。

回答by DiAgo

Had to do a bit of modification. I had to set the owner and activate the window. Check for the pop up window and activate the window as given below.

不得不做一些修改。我必须设置所有者并激活窗口。检查弹出窗口并激活如下所示的窗口。

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }