How can I remove all labels where Name
starts with "ToClear"?
I tried this code, but it clears them in two clicks (if there are 26 labels it only removes 13 per click)
private void ClearLabel()
{
foreach (var _object in this.Controls)
{
Console.WriteLine(((Label)_object).Name);
if (_object is Label && ((Label)_object).Name.StartsWith("ToClear"))
{
this.Controls.Remove(this.Controls[((Label)_object).Name]);
}
}
}
CodePudding user response:
I wonder that it does not throw an exception. You are enumerating a collection and inside of this loop you are modifying the source. Instead you should collect the controls to remove and then remove them. Easy and readable with LINQ:
var lblRemove = this.Controls.OfType<Label>().Where(l => Name.StartsWith("ToClear")).ToList();
lblRemove.ForEach(this.Controls.Remove);
Note that it will not find nested controls(like your approach). Therefore you have to use a recursive loop, like this: https://stackoverflow.com/a/65855106/284240
CodePudding user response:
The problem was the loop was modifying the collection while still looping over it. That's a no-no. You can do this:
private void ClearLabel()
{
SuspendLayout();
var toRemove = Controls.Where(c => c is Label && c.Name.StartsWith("ToClear")).ToList();
foreach(var control in toRemove)
{
Controls.Remove(control);
}
ResumeLayout();
}
CodePudding user response:
recurse. You can't remove while enumerating. Make a list first, then remove
NOTE: this works for the nested controls
private removeList = new Dictionary<Control, Label>();
private void EnumerateLabels(Control ctrl)
{
foreach (var c in ctrl.Controls)
{
if (c is Label && c.Name.StartsWith("ToClear"))
removeList.Add(ctrl, c);
EnumerateLabels(c); // recurse children
}
}
usage
// assuming `this` is a form
EnumerateLabels(this);
foreach (var kvp in removeList)
kvp.Key.Controls.Remove(kvp.Value);
Disclaimer - not tested
CodePudding user response:
You can do it via RemoveAll
:
this.Controls.RemoveAll(c => (c is Label) && c.Name.StartsWith("ToClear"));
See more here: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.removeall?view=net-6.0