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