假设您使用子窗口的Owner属性将父窗口与子窗口关联,我将使用基于事件的方法.
在您的子窗口中创建一个事件,通知侦听器将子窗口与其父窗口解除关联(分离):
public event EventHandler<EventArgs> DetachOwner;
Run Code Online (Sandbox Code Playgroud)
接下来需要确定何时应该引发此事件.为此,我们将在子窗口中使用了三件大事:Activated,Deactivated和LocationChanged.
LocationChanged将告诉我们子窗口何时移动但我们需要在子窗口移动时过滤掉因为它在父窗口之后的情况.为此,我们需要知道子窗口是否正在移动并且它是否具有焦点.要跟踪子窗口的焦点状态,请在Window的事件处理程序中创建一个名为bool字段HasFocus并设置HasFocus为true Activated,并在Window的Deactivated处理程序中设置为false .
将其添加到您的子窗口:
private void Window_LocationChanged(object sender, EventArgs e) {
if (HasFocus) {
if (DetachChild != null) {
DetachChild(this, EventArgs.Empty);
}
}
}
bool HasFocus;
private void Window_Activated(object sender, EventArgs e) {
HasFocus = true;
}
private void Window_Deactivated(object sender, EventArgs e) {
HasFocus = false;
}
Run Code Online (Sandbox Code Playgroud)
在父窗口中,您将DetachOwner在实例化子窗口时订阅子窗口的事件:
_child = new Child();
_child.Owner = this;
// Subscribe to the DetachOwner event.
_child.DetachChild += Child_DetachOwner;
Run Code Online (Sandbox Code Playgroud)
此DetachOwner处理程序只是将子Window的Owner属性设置为null:
void Child_DetachOwner(object sender, EventArgs e) {
((Child)sender).Owner = null;
}
Run Code Online (Sandbox Code Playgroud)
您可以通过在父窗口中使用处理程序在子窗口中创建类似的AttachOwner事件来扩展此方法以将子窗口重新附加到它的父窗口:
void Child_AttachOwner(object sender, EventArgs e) {
((Child)sender).Owner = this;
}
Run Code Online (Sandbox Code Playgroud)