在Parent's构造函数中设置Window's所有者时遇到问题

本文关键字:所有者 问题 Window 遇到 构造函数 Parent 设置 | 更新日期: 2023-09-27 18:13:38

在WPF中设置窗口的所有者属性到父窗体的构造函数中是否有任何错误?不应该有,对吧?那么为什么我从下面的代码得到一个XamlParseException ?

public partial class MainView : Window
{
    private readonly OwnedWindow owned;
    public MainView()
    {
        InitializeComponent();
        owned = new OwnedWindow();
        owned.DataContext = DataContext;
        var window = GetWindow(this);
        owned.Owner = this;  //Setting to window causes the same error
        ...
    }

我应该澄清,删除owned.Owner = this;也删除了运行时错误。

异常的详细信息:

XamlParseException was unhandled

类型为"…"的构造函数的调用MainView'匹配指定的绑定约束抛出异常。

实际上,我看了看内部异常,它说:

不能将Owner属性设置为未显示的窗口以前。

我正在调查这个

在Parent's构造函数中设置Window's所有者时遇到问题

问题是,因为WPF只在第一次显示WPF窗口时创建本机窗口,所以您不能将尚未显示的窗口设置为Owner(因为这建立了本机窗口"owner -> owned"的关系,但本机句柄还不存在)

您可以在所有者窗口上处理StateChanged事件,确保新状态"显示",然后在该点设置所有者窗口的Owner。或者,您可以创建并显示所拥有的窗口。

我最终订阅了Window.Activated,而不是Window.StateChanged。请务必在处理程序中取消订阅,正如评论中建议的那样。

    private void OnActivated(object sender, EventArgs eventArgs)
    {
        owned.Owner = this;
        Activated -= OnActivated;
    }

我接受了dlev的答案,因为它直接引导我找到了答案,尽管他的答案并不适合我的实际情况。

如果您出于某种原因需要比正常情况更早创建句柄,或者无法显示窗口,则添加另一个选项:

new WindowInteropHelper(myWindow).EnsureHandle();

您需要与HandleCreated事件等价的WPF事件,即SourceInitialized。这应该可以工作:

public OwnerWindow()
{
    InitializeComponent();
    SourceInitialized += (s, a) =>
        {
            var owned = new OwnedWindow();
            owned.Owner = this;
        };
}

请注意,您不必Show OwnerWindow或OwnedWindow为这个工作。