对话框出现在其他窗口后面

问题描述

我正在使用Prism对话框服务来创建未处理的异常对话框。我有一个启动画面窗口,尽管它没有设置TopMost属性(尝试过并且完全很痛苦:),但我在上面使用了Activate使其升至顶部因此它会在加载时显示在主窗口上。

问题是当引发异常并弹出我未处理的异常对话框时,它出现在初始屏幕的后面,使用户想知道发生了什么,直到他们注意到任务栏中有一个额外的按钮。

根据文档说明,该对话框是UserControl,并且没有Activate功能。当我尝试在构造函数获取父窗口的句柄时,Parent属性null

如何在其他窗口顶部显示对话框?

解决方法

Prism的对话框服务会自动将对话框的Owner设置为Window集合中找到的第一个活动Application.Current.Windows(如果对话框窗口尚未设置所有者)。它没有公开任何直接访问或激活窗口的方法。在MVVM服务中,您不会这样做。

在Prism Window。您必须为所有对话框共享该对话框宿主窗口类型,因此不能在自定义Owner中设置其他Window。由于实例化OwnernullWindow,因此其所有者将是第一个活动窗口。

如果您希望对话框的Owner是一个与初始屏幕一样的其他窗口,因此该行为是有问题的,那么它会自动或模态地显示在其顶部,或者根本没有所有者。

您无法在UserControl的构造函数中激活对话框,因为在实例化之前无法将其设置为父对话框主机Content的{​​{1}}。您要么必须使用Window集合来查找对话框,要么立即创建自定义对话框服务以激活或设置Application.Current.Windows

应用程序Windows

如果要在Owner中找到对话框宿主窗口,则可以在显示对话框并检查每个窗口的Application.Current.Windows之后过滤此集合,其中一个将包含您的Content类型。如果只显示一次未处理的异常对话框,那么将有一个带有此UserControl的窗口实例。如果您多次显示它,则可以通过在UserControl中传递DataContext来通过之前设置的DialogParameter访问其视图模型上的属性来标识当前实例。考虑创建服务。

自定义对话框服务

个人而言,我更喜欢创建自定义对话框服务,因为它使您可以更好地控制自己的工作。要创建一个自定义界面,以暴露内置Show的方法以及您自己的方法,从而满足您的需求。

IDialogService

我只是创建一个新方法public interface ICustomDialogService : IDialogService { public void ShowOrphan(string name,IDialogParameters parameters,Action<IDialogResult> callback); } 来显示一个没有所有者的对话框,该对话框在显示时会自动激活,因此位于前台。使其适应您的要求,例如传递显式所有者或仅传递所有者类型,以便对话框服务在应用程序窗口集合本身中搜索实例。

接下来,以ShowOrphan类型实现ICustomDialogService。您可以只从public repository复制代码。确保使用适用于您的Prism版本的代码,请参见标签

您不必进行太多更改。只需将新公共方法中的适当参数传递到CustomDialogService方法中即可,该方法负责设置窗口所有者。如果除了显示对话窗口外确实需要激活对话窗口,则可以在ConfigureDialogWindowProperties中进行。

ShowDialogInternal

完成后,您必须覆盖旧对话框服务的注册。

public class CustomDialogService : ICustomDialogService
{
   // ...other public members.

   public void ShowOrphan(string name,Action<IDialogResult> callback)
   {
      // Appended a new parameter "isOrphan"
      ShowDialogInternal(name,parameters,callback,false,true);
   }

   // ...other private members.

   // Appended a new parameter "isOrphan"
   void ConfigureDialogWindowProperties(IDialogWindow window,FrameworkElement dialogContent,IDialogAware viewModel,bool isOrphan)
   {
      // ...other code.

      if (isOrphan)
         return;

      if (window.Owner == null)
         window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
   }
}

现在您可以解析containerRegistry.RegisterSingleton <CustomDialogService>(); containerRegistry.Register<IDialogService,CustomDialogService>(); containerRegistry.Register<ICustomDialogService,CustomDialogService>(); 并使用其ICustomDialogService方法显示窗口。