如果窗体关闭,为什么控件计数会减少

本文关键字:控件 为什么 窗体 如果 | 更新日期: 2023-09-27 18:26:59

我有一个显示Form对象的面板。当在窗体上调用Close()方法时,panel.Controls.Count会被修改,Count会少一个。这怎么可能?

这是我在面板中显示表单的方式:

// insertForm is a windows form
insertForm.TopLevel = false;
insertForm.Dock = DockStyle.Fill;
insertForm.FormBorderStyle = FormBorderStyle.None;
this.pnlContent.Controls.Clear();
this.pnlContent.Controls.Add(insertForm);

当调用某个form.Close()时,pnlContentControls计数为0。那么,这怎么可能呢?调用Close()时会发生什么?

如果窗体关闭,为什么控件计数会减少

关闭一个窗体会导致该窗体被释放,进而导致该窗体从其父控件集合中删除。

如果你使用反编译器,你会注意到两件事:

  1. 将控件添加到ControlCollection时,控件的所有者将设置为ControlCollection's所有者。CCD_ 10调用CCD_
  2. 当一个控件被释放时,它会将自己从其所有者的ControlCollection中移除。本质上,Control.Dispose调用parent.Controls.Remove(this)

经验教训:不要将ControlCollection用作控件的通用集合类型它与WinForms深度集成,用于控制包含和父子关系。只有当您真正需要父控件包含子控件时,才使用此类型。

当窗体关闭时,对象内创建的所有资源都将关闭,窗体将被处理

http://msdn.microsoft.com/pt-br/library/system.windows.forms.form.close.aspx

Controls集合执行两项重要的工作。首先,它跟踪容器的子控件。控制对象在集合中的顺序决定了它们的Z顺序。其次,它注意确保控件在其父控件被销毁时得到处理。这就是为什么您不必像处理其他实现IDisposable的.NET类那样自己处理控件的原因。

这会导致代码中出现一个严重的错误,Controls.Clear()方法只是从集合中删除控件,而不处理它们。这是一个非常严重的泄漏,会使你的程序变得又胖又慢,最终导致它在Windows拒绝提供更多窗口句柄时崩溃。你需要这样写:

while (this.pnlContent.Controls.Count > 0) this.pnlContent.Controls[0].Dispose();

这也清楚地说明了为什么当您调用Close()方法时控件计数会下降,该方法会处理表单对象,并自动将其从容器的control集合中删除。

处理控件只会破坏控件使用的本机Windows操作系统资源。Handle属性是最明显的一个。否则,它不会使.NET对象消失,这需要运行垃圾收集器。保留对已处理控件的引用是个坏主意,只要有对它的引用,GC就不会销毁它,而且当你试图使用它时,你很容易得到ObjectDisposedException。