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

Jos*_*eph 16 c# wpf window .net-4.0

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

        ...
    }
Run Code Online (Sandbox Code Playgroud)

我应该澄清一下,删除它owned.Owner = this;也会删除运行时错误.

例外的细节:

XamlParseException未处理

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

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

无法将Owner属性设置为之前未显示的Window.

所以我现在正在调查.

dle*_*lev 12

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

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


Jos*_*eph 6

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

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

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


Bor*_* B. 5

您需要WPF HandleCreated事件的等效项,即SourceInitialized。这应该工作:

public OwnerWindow()
{
    InitializeComponent();

    SourceInitialized += (s, a) =>
        {
            var owned = new OwnedWindow();
            owned.Owner = this;
        };
}
Run Code Online (Sandbox Code Playgroud)

请注意,您不必Show使用OwnerWindow或OwnedWindow即可运行。


Gaz*_*yer 5

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

new WindowInteropHelper(myWindow).EnsureHandle();