更改 Prism DialogWindow 的所有者

Change Owner of Prism DialogWindow

我已经使用 MVVM 在 WPF 中实现了新的 IDialogService。我的对话框工作正常,除了当我在前台打开另一个 window 时,对话框将出现在 window.

的中心

我想要实现的是 Dialog 始终位于 Main Window 的中心。这可以通过设置 DialogWindowOwner 属性(类型 Window 和对话框 UserControlParent 来应用我创建)到 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 单独设置为每个对话框视图的所有者。