更改 Prism DialogWindow 的所有者
Change Owner of Prism DialogWindow
我已经使用 MVVM 在 WPF 中实现了新的 IDialogService
。我的对话框工作正常,除了当我在前台打开另一个 window 时,对话框将出现在 window.
的中心
我想要实现的是 Dialog 始终位于 Main Window 的中心。这可以通过设置 DialogWindow
的 Owner
属性(类型 Window
和对话框 UserControl
的 Parent
来应用我创建)到 Application.Current.MainWindow
.
我现在发现,可以更改 DialogWindow
的样式,如图 所示。但我看不出有任何可能以这种方式更改 Owner
属性。
我已经尝试通过访问 UserControl
CodeBehind 中的 Parent
来设置 Owner
属性。但它要么为空 (OnInitialized
),要么无法更改,因为 'the DialogWindow
is already displayed' (OnLoaded
/OnApplyTemplate
).
你对如何解决这个问题有什么建议吗?
Prism 对话服务默认将第一个活动window设置为对话的所有者。这就是它的实施方式。有多种方法可以将主要 window 设置为所有者,或多或少需要付出不同的努力和不同的约束,但它需要一些定制。才写了一个月
替换对话框window
您可以通过从 Window
派生并实现 IDialogWindow
.
来定义新的对话宿主 window
public class DialogWindow : Window, IDialogWindow
{
public DialogWindow()
{
Owner = System.Windows.Application.Current.MainWindow;
WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
public IDialogResult Result { get; set; }
}
然后在你的容器中注册它。这样 所有对话框 将在主要 window.
中居中
containerRegistry.Register<IDialogWindow, DialogWindow>();
您还可以在对话框 window 样式中设置 window 启动位置,而不是对话框 window class.
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
</Style>
</prism:Dialog.WindowStyle>
这种方法在 Prism 的更高版本中可能会更有趣,它可能允许注册多个命名对话框 windows。然后您可以在特殊情况下使用自定义 window,否则使用默认 window。
自定义对话服务
您可以只复制 DialogService
implementation from Prism 并根据您的需要进行调整。在 ConfigureDialogWindowProperties
中更改设置所有者的行 window.
window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
将默认活动 window 替换为主要 window。
window.Owner = System.Windows.Application.Current.MainWindow;
不要忘记在容器中注册自定义对话框服务以覆盖默认服务。
containerRegistry.RegisterSingleton<IDialogService, CustomDialogService>();
具有附加属性的自定义对话服务
如果您需要更多自定义行为,请考虑使用 attached properties 使此 ower 逻辑参数化,您可以在用户控件上设置并在自定义对话框服务中读取。这是最灵活的方法,但也是最需要努力的方法。它允许单独定制每个对话框。
public class WindowOwnerAttachedProperties
{
public static readonly DependencyProperty IsMainWindowOwnerProperty = DependencyProperty.RegisterAttached("IsMainWindowOwner", typeof(bool), typeof(WindowOwnerAttachedProperties), new PropertyMetadata(false));
public static bool GetIsMainWindowOwner(DependencyObject dependencyObject)
{
return (bool)dependencyObject.GetValue(IsMainWindowOwnerProperty);
}
public static void SetIsMainWindowOwner(DependencyObject dependencyObject, Window value)
{
dependencyObject.SetValue(IsMainWindowOwnerProperty, value);
}
}
在您的对话框用户控件中设置附加的 属性。
<UserControl x:Class="Your.Namespace"
...
attachedProperties:WindowOwnerAttachedProperties.IsMainWindowOwner="True">
根据自定义对话框服务中的附加属性设置 window 所有者。
if (window.Owner == null && WindowOwnerAttachedProperties.GetIsMainWindowOwner(dialogContent))
window.Owner = System.Windows.Application.Current.MainWindow;
else if (window.Owner == null)
window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
这让您可以选择使用默认行为来实现向后兼容性,或者将主要 window 单独设置为每个对话框视图的所有者。
我已经使用 MVVM 在 WPF 中实现了新的 IDialogService
。我的对话框工作正常,除了当我在前台打开另一个 window 时,对话框将出现在 window.
我想要实现的是 Dialog 始终位于 Main Window 的中心。这可以通过设置 DialogWindow
的 Owner
属性(类型 Window
和对话框 UserControl
的 Parent
来应用我创建)到 Application.Current.MainWindow
.
我现在发现,可以更改 DialogWindow
的样式,如图 Owner
属性。
我已经尝试通过访问 UserControl
CodeBehind 中的 Parent
来设置 Owner
属性。但它要么为空 (OnInitialized
),要么无法更改,因为 'the DialogWindow
is already displayed' (OnLoaded
/OnApplyTemplate
).
你对如何解决这个问题有什么建议吗?
Prism 对话服务默认将第一个活动window设置为对话的所有者。这就是它的实施方式。有多种方法可以将主要 window 设置为所有者,或多或少需要付出不同的努力和不同的约束,但它需要一些定制。才写了一个月
替换对话框window
您可以通过从 Window
派生并实现 IDialogWindow
.
public class DialogWindow : Window, IDialogWindow
{
public DialogWindow()
{
Owner = System.Windows.Application.Current.MainWindow;
WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
public IDialogResult Result { get; set; }
}
然后在你的容器中注册它。这样 所有对话框 将在主要 window.
中居中containerRegistry.Register<IDialogWindow, DialogWindow>();
您还可以在对话框 window 样式中设置 window 启动位置,而不是对话框 window class.
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
</Style>
</prism:Dialog.WindowStyle>
这种方法在 Prism 的更高版本中可能会更有趣,它可能允许注册多个命名对话框 windows。然后您可以在特殊情况下使用自定义 window,否则使用默认 window。
自定义对话服务
您可以只复制 DialogService
implementation from Prism 并根据您的需要进行调整。在 ConfigureDialogWindowProperties
中更改设置所有者的行 window.
window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
将默认活动 window 替换为主要 window。
window.Owner = System.Windows.Application.Current.MainWindow;
不要忘记在容器中注册自定义对话框服务以覆盖默认服务。
containerRegistry.RegisterSingleton<IDialogService, CustomDialogService>();
具有附加属性的自定义对话服务
如果您需要更多自定义行为,请考虑使用 attached properties 使此 ower 逻辑参数化,您可以在用户控件上设置并在自定义对话框服务中读取。这是最灵活的方法,但也是最需要努力的方法。它允许单独定制每个对话框。
public class WindowOwnerAttachedProperties
{
public static readonly DependencyProperty IsMainWindowOwnerProperty = DependencyProperty.RegisterAttached("IsMainWindowOwner", typeof(bool), typeof(WindowOwnerAttachedProperties), new PropertyMetadata(false));
public static bool GetIsMainWindowOwner(DependencyObject dependencyObject)
{
return (bool)dependencyObject.GetValue(IsMainWindowOwnerProperty);
}
public static void SetIsMainWindowOwner(DependencyObject dependencyObject, Window value)
{
dependencyObject.SetValue(IsMainWindowOwnerProperty, value);
}
}
在您的对话框用户控件中设置附加的 属性。
<UserControl x:Class="Your.Namespace"
...
attachedProperties:WindowOwnerAttachedProperties.IsMainWindowOwner="True">
根据自定义对话框服务中的附加属性设置 window 所有者。
if (window.Owner == null && WindowOwnerAttachedProperties.GetIsMainWindowOwner(dialogContent))
window.Owner = System.Windows.Application.Current.MainWindow;
else if (window.Owner == null)
window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
这让您可以选择使用默认行为来实现向后兼容性,或者将主要 window 单独设置为每个对话框视图的所有者。