在Parent的构造函数中设置窗口所有者的麻烦

时间:2013-05-14 18:50:45

标签: c# wpf .net-4.0 window

WPF中是否有任何错误,将窗口的Owner属性设置为该父窗口构造函数中的父窗口?不应该,对吗?那么为什么我从以下代码中获得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未处理

  

在匹配的类型'... MainView'上调用构造函数   指定的绑定约束引发了异常。

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

  

无法将Owner属性设置为尚未显示的Window   先前。

所以我现在正在调查。

4 个答案:

答案 0 :(得分:12)

问题在于,因为WPF仅在第一次显示WPF窗口时创建本机窗口,所以您不能将尚未显示的窗口设置为Owner(因为它会建立本机窗口) “owner - >拥有”关系,但原生句柄尚不存在。)

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

答案 1 :(得分:5)

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

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

我接受了dlev的回答,因为它直接导致我找到答案,即使他的确不适合我的确切情况。

答案 2 :(得分:5)

您需要相当于HandleCreated事件的WPF,即SourceInitialized。这应该有效:

public OwnerWindow()
{
    InitializeComponent();

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

请注意,您不必使用Show OwnerWindow或OwnedWindow来实现此目的。

答案 3 :(得分:1)

如果由于某种原因需要先于正常创建的句柄,或者无法显示窗口,只需添加另一个选项:

new WindowInteropHelper(myWindow).EnsureHandle();