Patryk
Patryk

Reputation: 24140

Why controls do not want to get removed?

I am trying to remove all the controls that are contained in my winform panel but they simply do not want to get removed - some of them are removed and some of them not. I have tried 2 approaches already and nothing:

  1. foreach

    foreach (Control controlEntry in this.contentsPanel.Controls)
    {
        this.contentsPanel.Controls.Remove(controlEntry);
    }
    
  2. for

    for (int i = 0; i < this.contentsPanel.Controls.Count; i++)
    {
        this.contentsPanel.Controls.RemoveAt(i);
    }
    

Why is this happening ?

Upvotes: 4

Views: 3056

Answers (5)

user21958984
user21958984

Reputation: 1

In case of webbrowser control, file is not free with contentsPanel.Controls.Clear(); or with contentsPanel.Controls.Remove(i);

use while (contentsPanel.Controls.Count > 0) contentsPanel.Controls[0].Dispose();

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 942247

You have to watch out for code like this, removing controls from their container like this produces an unrecoverable resource leak. Controls.Remove/At(), or the Controls.Clear() method as suggested by other posters, removes the control from the collection and re-hosts it to the "parking window". An otherwise invisible window where the native window can find a hospitable home without having to be destroyed. Ready to be re-hosted on another parent.

Which is the trap, you typically don't move it to another parent. The control will continue to survive on the parking window, consuming native Windows resources. The garbage collector cannot recover these resources. Eventually your program will crash when Windows refuses to provide more windows to your process. The exception message will say "Error creating handle".

Instead, you must dispose the control. Which also automatically removes the control from its parent. The proper code is:

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

Or iterate backwards if you find this a bit too bizarre looking.

Upvotes: 18

Marc Gravell
Marc Gravell

Reputation: 1063964

The foreach will fail because you are changing the collection, which breaks the iterator.

The for fails because you are only removing every other item; consider: i=0, you remove the zeroth item. Now the item that was item 1 is item 0 - so when you remove item 1 (next loop iteration) you have jumped one.

Short version: use Clear():

contentsPanel.Controls.Clear();

Longer version: iterate backwards:

for(int i=contentsPanel.Controls.Count-1; i>=0;i--) {
   contentsPanel.Controls.RemoveAt(i);
}

The first (Clear) is simpler.

Upvotes: 3

Sebastian Piu
Sebastian Piu

Reputation: 8008

If you want to remove them all then just do

this.contentsPanel.Controls.Clear()

Upvotes: 4

user418938
user418938

Reputation:

Each time you remove control from collection, the collection changes. When you remove 1st element of Controls, 2nd element becomes 1st, so when you proceed to delete 2nd control, you are in fact removing 3rd element from original collection (skipping 2nd element).

If you want to remove all controls contained in collection, use this.contentsPanel.Controls.Clear(). If you want to remove controls by their indices in ControlCollection, first select controls to remove to separate list or array and then remove them.

Upvotes: 9

Related Questions