ShowDialog()在父窗口后面

10

我正在使用ShowDialog()WindowStyle = WindowStyle.SingleBorderWindow;在我的WPF(MVVM)应用程序中打开一个模态窗口,但它允许我通过Windows任务栏导航到父窗口(Windows 7)。

我在这里找到了一个答案:WPF和ShowDialog(),但它对我来说不太适用,因为我不需要一个"始终置顶"的工具窗口。

提前致谢

7个回答

14

尝试设置对话框的Owner属性。那应该可以工作。

Window dialog = new Window();
dialog.Owner = mainWindow;
dialog.ShowDialog();

编辑: 我在使用MVVM时遇到了一个类似的问题。您可以通过使用委托来解决这个问题。

public class MainWindowViewModel
{
    public delegate void ShowDialogDelegate(string message);
    public ShowDialogDelegate ShowDialogCallback;

    public void Action()
    {
        // here you want to show the dialog
        ShowDialogDelegate callback = ShowDialogCallback;
        if(callback != null)
        {
            callback("Message");
        }
    }
}

public class MainWindow
{
    public MainWindow()
    {
        // initialize the ViewModel
        MainWindowViewModel viewModel = new MainWindowViewModel();
        viewModel.ShowDialogCallback += ShowDialog;
        DataContext = viewModel;
    }

    private void ShowDialog(string message)
    {
        // show the dialog
    }
}

2
谢谢,这个想法很好。但目前唯一的问题是在ViewModel中没有View的信息。我尝试了App.Current.MainWindow,它可以工作,但不是最好的解决方案。也许我应该重新考虑我的MVVM模式结构。 - Oszkar
1
我为MVVM问题添加了一个可能的解决方案。 - MatthiasG
1
@Oszkar 我使用了 Application.Current.MainWindow(使用 Application 而不是 App),由于它是静态的,所以没有影响 MVVM,一切都很顺利。 - heltonbiker

5

我遇到了这个问题,但是由于窗口是从视图模型中打开的,我没有当前窗口的引用。要解决这个问题,我使用了以下代码:

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设置为窗口的所有者,使其所有者成为其祖父窗口,而不是父窗口。


1

当父窗口创建(并显示)子窗口时,您需要设置所有者。

public partial class MainWindow : Window
{

    private void openChild()
    {
        ChildWindow child = new ChildWindow ();
        child.Owner = this; // "this" is the parent
        child.ShowDialog();
    }
 }

此外,如果您不想为所有子任务单独设置一个额外的任务栏...那么。
<Window x:Class="ChildWindow"           
        ShowInTaskbar="False" >
</Window>

如果“this”不是一个窗口怎么办?我正在从MFC运行WPF,因此我没有应用程序或主窗口。 - Jim Balter
你想要打开什么?只是显示一个对话框吗? 如果你不是想将对话框附加到窗口上,我就不明白你的问题了。 - 00jt
正如我所说的,“来自MFC”…… MFC类并不派生自WPF的Window。我最近发现了WindowInteropHelper.Owner……即使如此,我们最终还是会有隐藏的模态对话框。 - Jim Balter
抱歉,我错过了那个。我不确定如何使WPF的所有者成为MFC。 - 00jt

1
问题似乎与 Window.Owner 有关,如果你根据以往对 Win32 API 和 WinForms 的知识判断,缺少所有者将是这种问题的典型原因,但正如许多人指出的那样,在 WPF 的情况下并非如此。微软不断改变事物以保持有趣。
在 WPF 中,您可以拥有具有特定所有者的对话框,并且仍然可以在任务栏中显示对话框。因为为什么不呢。这是默认行为。因为为什么不呢。他们的理由是模态对话框不再合适,因此您不应该使用它们;您应该使用无模式对话框,这些对话框作为单独的任务栏图标显示是有意义的,在任何情况下,用户都可以决定是否要将不同的应用程序窗口显示为单独的图标,还是想要将它们分组显示。
因此,他们试图强制执行此政策,完全不考虑可能想违反其准则并创建模态对话框的任何人。因此,他们强制您明确声明不希望为对话框显示任务栏图标。
要解决此问题,请在视图类的构造函数中执行以下操作:
ShowInTaskbar = false;

这可能发生在InitializeComponent();之后。

这与Xcalibur37的答案相同,但我认为,由于WPF强制你拥有一个.cs文件和一个.xaml文件,因此你可以将不太可能更改的东西放在.cs文件中。


1
MVVM模式的主要原因之一是为了使您的交互逻辑可以进行单元测试。因此,您不应该直接从ViewModel打开窗口,否则将在单元测试中弹出对话框。
相反,您应该引发一个事件,由View处理并为您打开对话框。例如,请参见Interaction Requests上的这篇文章:https://msdn.microsoft.com/en-us/library/gg405494(v=pandp.40).aspx#sec12

0
添加 "ShowInTaskbar" 并将其设置为 false。

0
即使这篇文章有点旧,我希望我发布我的解决方案是可以的。 所有上述结果对我来说都是已知的,但并没有完全产生期望的结果。
我为其他谷歌用户做这件事 :)
假设f2是您想要显示在f1之上的窗口:
f2.Owner = Window.GetWindow(this);
f2.ShowDialog();

就是这样,我保证它不会消失!

希望有所帮助, Guy


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