简体   繁体   中英

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.

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.

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

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();
}

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--;
          }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM