如何解决对话框出现在其他窗口后面
我正在使用Prism对话框服务来创建未处理的异常对话框。我有一个启动画面窗口,尽管它没有设置TopMost
属性(尝试过并且完全很痛苦:),但我在上面使用了Activate
使其升至顶部因此它会在加载时显示在主窗口上。
问题是当引发异常并弹出我未处理的异常对话框时,它出现在初始屏幕的后面,使用户想知道发生了什么,直到他们注意到任务栏中有一个额外的按钮。
根据文档说明,该对话框是UserControl
,并且没有Activate
功能。当我尝试在构造函数中获取父窗口的句柄时,Parent
属性为null
。
如何在其他窗口顶部显示对话框?
解决方法
Prism的对话框服务会自动将对话框的Owner
设置为Window
集合中找到的第一个活动Application.Current.Windows
(如果对话框窗口尚未设置所有者)。它没有公开任何直接访问或激活窗口的方法。在MVVM服务中,您不会这样做。
在Prism Window。您必须为所有对话框共享该对话框宿主窗口类型,因此不能在自定义Owner
中设置其他Window
。由于实例化Owner
时null
是Window
,因此其所有者将是第一个活动窗口。
如果您希望对话框的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
方法显示窗口。