在Parent的构造函数中设置窗口所有者的麻烦
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’上调用与指定绑定约束匹配的构造函数引发了exception。
实际上 ,我查看了内部exception,它说:
无法将Owner属性设置为之前未显示的Window。
所以我现在正在调查。
问题是,因为WPF仅在第一次显示WPF窗口时创建本机窗口,所以您不能将尚未显示的窗口设置为Owner
(因为它建立了本机窗口“所有者 – >拥有”关系,但原生句柄尚不存在。)
您可以在所有者窗口上处理StateChanged
事件,确保“显示”新状态,然后在该点设置拥有窗口的Owner
。 或者,您可以在该点创建并显示拥有的窗口。
我最终订阅了Window.Activated
,而不是Window.StateChanged
。 请务必按照评论中的建议在处理程序中取消订阅。
private void OnActivated(object sender, EventArgs eventArgs) { owned.Owner = this; Activated -= OnActivated; }
我接受了dlev的答案,因为它让我直接找到答案,即使他的确不适合我的确切情况。
你需要WPF等效的HandleCreated
事件,它是SourceInitialized
。 这应该工作:
public OwnerWindow() { InitializeComponent(); SourceInitialized += (s, a) => { var owned = new OwnedWindow(); owned.Owner = this; }; }
请注意,您无需Show
OwnerWindow或OwnedWindow即可。
如果由于某种原因需要先于正常创建的句柄,或者无法显示窗口,只需添加另一个选项:
new WindowInteropHelper(myWindow).EnsureHandle();