对话框出现在其他 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
。由于 Owner
是 null
,当实例化 Window
时,它的所有者将是第一个活动的 window。
如果您希望对话框的 Owner
与初始屏幕不同 window,则此行为会出现问题,因此它会自动或模态显示在其顶部,或者没有所有者全部.
您无法在 UserControl
的构造函数中激活对话框,因为在实例化之前无法将其设置为父对话框宿主 Window
的 Content
。您要么必须使用 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。
我正在使用 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
。由于 Owner
是 null
,当实例化 Window
时,它的所有者将是第一个活动的 window。
如果您希望对话框的 Owner
与初始屏幕不同 window,则此行为会出现问题,因此它会自动或模态显示在其顶部,或者没有所有者全部.
您无法在 UserControl
的构造函数中激活对话框,因为在实例化之前无法将其设置为父对话框宿主 Window
的 Content
。您要么必须使用 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。