对话框出现在其他 windows 后面

Dialog appears behind other windows

我正在使用 Prism 对话框服务创建未处理的异常对话框。我有一个闪屏 window,虽然它没有 TopMost 属性 设置(试过了,但非常糟糕:),我在上面使用 Activate让它上升到顶部,以便它在加载时出现在主要 window 上。

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

该对话框是 UserControl,如文档所述,它没有 Activate 功能。当我尝试在构造函数中获取父 window 的句柄时,Parent 属性 是 null.

如何将对话框置于其他 windows 的顶部?

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

在 Prism <= 7.x 中,您只能有一个对话 window 主机。默认情况下,这是一个常规 Window。您必须为所有对话共享此对话主机 window 类型,因此无法在自定义 Window 中设置不同的 Owner。由于 Ownernull,当实例化 Window 时,它的所有者将是第一个活动的 window。

如果您希望对话框的 Owner 与初始屏幕不同 window,则此行为会出现问题,因此它会自动或模态显示在其顶部,或者没有所有者全部.

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

申请Windows

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

自定义对话服务

就个人而言,我更喜欢创建自定义对话服务,因为它可以让您更好地控制自己正在做的事情。根据您的要求创建一个公开 built-in IDialogService 方法以及您自己的方法的自定义界面。

public interface ICustomDialogService : IDialogService
{
   public void ShowOrphan(string name, IDialogParameters parameters, Action<IDialogResult> callback);
}

我只是创建了一个新方法 ShowOrphan 来显示一个没有所有者并且在显示时自动激活的对话框,因此它位于前台。根据您的要求调整它,例如传入一个明确的所有者或只是一个所有者类型,以便对话服务在应用程序 window 集合本身中搜索一个实例。

接下来,在 CustomDialogService 类型中实现 ICustomDialogService。您可以直接从 public repository 复制代码。请务必使用适用于您的 Prism 版本的代码,请参阅 Tags

您不必进行太多更改。只需将新 public 方法中的适当参数传递给 ConfigureDialogWindowProperties 方法,该方法负责设置 window 所有者。如果除了显示它之外确实需要激活对话框 window,您可以在 ShowDialogInternal.

中执行此操作
public class CustomDialogService : ICustomDialogService
{
   // ...other public members.

   public void ShowOrphan(string name, IDialogParameters parameters, 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 并使用其 ShowOrphan 方法显示 window。