c# - Prism IDialogService 显示非模态对话框充当模态
问题描述
在 WPF Prism 7.2 中,我已按照IDialogService
此处显示的说明进行操作。
我有PlotsDialogPanel
UserControl
一个单ContentControl
,如下所示:
<UserControl x:Class="PlotModule.Dialogs.Views.PlotsDialogPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:local="clr-namespace:PlotModule.Dialogs.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ResizeMode" Value="CanResizeWithGrip"/>
<Setter Property="ShowInTaskbar" Value="True"/>
</Style>
</prism:Dialog.WindowStyle>
<Grid>
<ContentControl prism:RegionManager.RegionName="PlotsDialogDisplayRegion" />
</Grid>
</UserControl>
在我的PlotModule
RegisterTypes
方法中,我注册了对话框:
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<PlotsDialogPanel, PlotsDialogPanelViewModel>();
}
但是当对话框显示在事件处理程序中时,它充当模式,它始终位于父级的最顶层。
private void MainMenuEventHandler(string inParameter)
{
_DialogService.Show("PlotsDialogPanel", new DialogParameters(), r => {});
}
我在这里看不到我做错了什么,关于为什么对话框表现为模态的任何想法?其他一切都按预期工作,对话框显示并关闭,IDialogAware::OnDialogOpened
并按OnDialogClosed
预期运行。
解决方案
它实际上不是模态的,只是最顶部的窗口。使用ShowDialog
an 方法显示一个模态对话框,它不仅会成为最顶层的窗口,而且还会禁用任何用户与其所有者窗口的交互,直到被关闭。
对话框位于另一个窗口之上的原因是它有一个所有者窗口分配给它的Owner
属性。默认情况下,Prism 将始终将应用程序中的第一个活动窗口分配为对话框的所有者,除非您在对话框宿主窗口上明确设置了一个不为空的所有者。
DialogService
请参阅GitHub 上的实现以供参考。此行设置Owner
对话框的。
if (window.Owner == null)
window.Owner = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
由于这是DialogService
实现的方式,因此您必须创建自己的对话服务并更改行为。例如,您可以提供重载以不设置所有者。实现原始IDialogService
接口以提供与默认实现的兼容性。
public interface ICustomDialogService : IDialogService
{
public void ShowOrphan(string name, IDialogParameters parameters, Action<IDialogResult> callback);
}
创建一个CustomDialogService
派生自 GitHub 的类型,ICustomDialogService
并从 GitHub 复制原始实现。通过将参数传递给ConfigureDialogWindowProperties
方法来调整原始方法,以确定是否设置Owner
并采取相应措施。
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>();
可能还有其他解决方法,例如创建忽略Owner
属性或其他黑客的自定义对话框主机窗口,但我认为创建自定义对话框服务是这里最干净的方法。
推荐阅读
- android-studio - 在android studio中遇到设计不可见问题怎么办?
- c++ - 在函数中使用特定的 std::get 重载
- javascript - 如何使用元素上的javascript在滚动上加载文件
? - python - 如何在 python 中创建蜘蛛网模型
- docker - 将隐藏文件包含到 io.fabric8:docker-maven-plugin 的 docker 映像中
- amazon-s3 - 回形针 + S3 的 Rspec
- delphi - 在 Delphi 10.4 中,当通过 TWebBroswer 连接时,如何将客户端 tcp 端口提供给 WebBroker (TWebModule)?
- python - 使用正则表达式 django 从 URL 获取列表
- html - 如何获得分配给 ForeignKey 的下一个元素?
- java - SecurityConfig [Spring boot 版本 2.5.x]:api 网关不会重定向/转发到服务并始终返回 401