Martijn
Martijn

Reputation: 24789

Why is the control count decreased if a form is closed?

I have a panel which displays Form objects. When the Close() method is called on a form, the panel.Controls.Count is modified, the Count is one less. How is this possible?

This is the way I show a form in th panel:

// 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);

And when somewhere form.Close() is called, the Controls count of pnlContent is 0. So, how is this possible? What all happens when Close() is called?

Upvotes: 4

Views: 225

Answers (3)

Hans Passant
Hans Passant

Reputation: 941457

The Controls collection performs two important jobs. First it keeps track of the child controls of a container. The order of the control objects in the collection determines their Z-order. Secondly, it takes care of ensuring that controls are disposed when their parent is destroyed. Which is the reason that you don't have to dispose controls yourself like you often need to do with other .NET classes that implement IDisposable.

Which leads to a nasty bug in your code, the Controls.Clear() method just removes controls from the collection, it does not dispose them. That a very bad leak that will make your program fat and slow, eventually causing it to crash when Windows refuse to give it any more window handles. You'll need to write it like this:

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

Which now also makes it obvious why the control count goes down when you call the Close() method, that disposes the form object which automatically removes it from its container's Control collection.

Disposing a control just destroys the native Windows operating system resources used by the control. The Handle property being the most obvious one. It does not otherwise make the .NET object disappear, that requires the garbage collector to run. Keeping a reference to a disposed control is a bad idea, the GC won't destroy it as long as there's a reference to it and you're apt to get an ObjectDisposedException when you try to use it anyway.

Upvotes: 1

Ani
Ani

Reputation: 113402

Closing a form causes the form to be disposed, which in turn causes it to be removed from its parent's control-collection.

If you use a decompiler, you will notice two things:

  1. When you add a control to a ControlCollection, the control's owner is set as the ControlCollection's owner. ControlCollection.Add(Control value) calls value.AssignParent(this.owner).
  2. When a control is disposed, it removes itself from its owner's ControlCollection. Essentially, Control.Dispose calls parent.Controls.Remove(this).

Lesson learned: Don't use a ControlCollection as general purpose collection-type for Controls. It is deeply integrated into WinForms for control-containment and parent-child relationships. Use this type only when you genuinely require a parent control to contain a child control.

Upvotes: 5

SalataLuc
SalataLuc

Reputation: 410

When a form is closed, all resources created within the object are closed and the form is disposed

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

Upvotes: 1

Related Questions