Nabegh
Nabegh

Reputation: 3299

Removing dynamically added controls from WinForm

I have a GroupBox in which I dynamically add controls into it. The controls I add are of two types DevExpress.XtraEditors.TextEdit and Windows.Forms.Label I am trying to remove these controls using the following

foreach (Control control in salesBox.Controls)
{
  control.Dispose(); 
  salesBox.Controls.Remove(control);
} 

This is correctly removing the TextEdit controls but not the Label controls. The loop is not iterating through the Label controls.

Upvotes: 4

Views: 11887

Answers (4)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112772

The easiest way to remove all controls from a controls collection is to call its Clear method:

salesBox.Controls.Clear();

Modifying collections can invalidate enumerators and yield unpredictable results or even throw an InvalidOperationException, depending on the collection type (see the "Remarks" section in IEnumerable.GetEnumerator Method on MSDN). Since foreach uses an enumerator you should not alter the collection it is iterating.

Use a for statement, if you have to delete selectively and also iterate backwards, in order not to get wrong index values after removing items:

for (int i = salesBox.Controls.Count - 1; i >= 0; i--) {
    Control c = salesBox.Controls[i];
    if (c is TextEdit || c is Label) {
        salesBox.Controls.RemoveAt(i);
    }
}

Upvotes: 6

Hans Passant
Hans Passant

Reputation: 942488

It doesn't work because you are modifying the collection you are iterating. Calling the Dispose() method also removes a control from the parent's Control collection. The side-effect is that you'll only dispose the even numbered controls. Either of these two loops will get the job done:

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

for (int ix = salesBox.Controls.Count-1; ix >= 0; ix---) salesBox.Controls[ix].Dispose();

Or keep them on a panel and dispose the panel.

Upvotes: 3

Po-ta-toe
Po-ta-toe

Reputation: 732

You cannot alter the contents of the collection within the Foreach. You would need to do something like this I believe.

List<Control> toRemove = salesBox.Controls.OfType<Control>().ToList();

foreach(Control c in toRemove)
{
 salesBox.Controls.Remove(c);
 c.Dispose();
}

Upvotes: 2

aliassce
aliassce

Reputation: 1197

Foreach can't iterate because the length of the salesbox.Controls changed. If you add or remove an item you'd better use for You can do it by

   for(int i=0;i<salesBox.Controls.Count;i++)
    {      if(salesBox.Controls[i] is DevExpress.XtraEditors.TextEdit) //your condition here
           { 
             salesBox.Controls.Remove(salesBox.Controls[i]);
             i--;
          }
    }

Upvotes: 0

Related Questions