26

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

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

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

提前致谢!

4

5 回答 5

63

没有任何代码可以以此为基础,但听起来您已经在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();
于 2011-06-20T21:17:26.123 回答
13

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

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
于 2012-03-20T16:05:38.510 回答
12

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

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

Activated += WindowActivated;

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

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

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

于 2012-01-13T07:38:05.533 回答
3

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

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

我最初使用:

myWindow.Owner = Application.Current.MainWindow;

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

MainWindow
   |
   -----> ChildWindow1

               |
               ----->  ChildWindow2

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

为了加快速度,我已将其作为代码片段添加到 Visual Studio 中。如果将以下内容添加到 Tools --> Code Snippet Manager --> My Code Snippets:

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

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

于 2014-03-07T10:46:42.820 回答
1

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

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }
于 2012-05-05T06:52:15.047 回答