wpf 在父构造函数中设置窗口所有者时遇到问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16550621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:47:51  来源:igfitidea点击:

Having Trouble Setting Window's Owner in Parent's Constructor

c#wpf.net-4.0window

提问by Joseph

Is there anything wrong in WPF with setting the Owner property of a window to its parent in that parent's constructor? There shouldn't be, right? So why am I getting an XamlParseExceptionfrom the following code?

在 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

        ...
    }

I should clarify that removing the owned.Owner = this;also removes the runtime error.

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

The details of the exception:

异常详情:

XamlParseException was unhandled

XamlParseException 未处理

The invocation of the constructor on type '...MainView' that matches the specified binding constraints threw an exception.

对与指定绑定约束匹配的类型“...MainView”的构造函数的调用引发了异常。

Actually, I looked at the Inner Exception, and it says:

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

Cannot set Owner property to a Window that has not been shown previously.

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

So I'm looking into that now.

所以我现在正在研究这个。

采纳答案by dlev

The problem is that because WPF only creates the native window the first time a WPF Window is shown, you can't be setting a not-yet-shown Window as an Owner(since that establishes a native window "owner -> owned" relationship, but the native handle doesn't yet exist.)

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

You can handle the StateChangedevent on the owner window, ensure that the new state is "shown", and then set the owned window's Ownerat that point. Alternatively, you could create and showthe owned window at that point.

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

回答by Joseph

I ended up subscribing to Window.Activated, not Window.StateChanged. Be sure to unsubscribe to it in the handler, as advised in the comments.

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

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

I accepted dlev's answer because it led me directly to finding the answer, even if his didn't work for my exact situation.

我接受了 dlev 的回答,因为它让我直接找到了答案,即使他的答案并不适合我的具体情况。

回答by Boris B.

You need the WPF equivalent of HandleCreatedevent, which is SourceInitialized. This should work:

您需要HandleCreated事件的 WPF 等效项,即SourceInitialized. 这应该有效:

public OwnerWindow()
{
    InitializeComponent();

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

Note that you don't have to Showeither OwnerWindow or OwnedWindow for this to work.

请注意,您不必Show使用 OwnerWindow 或 OwnedWindow 来使其工作。

回答by GazTheDestroyer

Just adding another option if you need the handle created earlier than normal for some reason, or can't show the window:

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

new WindowInteropHelper(myWindow).EnsureHandle();

new WindowInteropHelper(myWindow).EnsureHandle();