I have a Panel that, in turn, has 4 panels inside. The interior panels are named "XXXX | 1 | A", "XXXX | 1 | B", "XXXX | 1 | C" and "XXXX | 1 | D", as you can see to differentiate them in the last character it has a letter.
In this case, what I want to do is always delete only the panels that are identified as A and B.
This is my code.
Dim clickedLabel = DirectCast(DirectCast(DirectCast(sender, ToolStripMenuItem).Owner, ContextMenuStrip).SourceControl, Panel)
pb = clickedLabel.Parent
Dim controls_number As Integer = pb.Controls.Count
Dim spliterb
Dim con As Control
For Each con In pb.Controls
spliterb = con.Name.Split("|")
If spliterb(2).ToString = ("A") Or spliterb(2).ToString = ("B") Then
pb.Controls.Remove(con)
End If
Next
As you can see, with the variable controls_number I know that there are 4 Panels inside, but when going through the arrangement, it only reads 3 and only removes the Panel that is identified as B and does not reach Panel A.
Can you explain to me why you don't read the 4 Panels? Any ideas for me to go through all 4?
Thank you.
Don't EVER modify a list while enumerating it with a For Each
loop. The simple solution in this and many other cases is to extract the items you want into a separate list and loop through that while removing the items from the original list. The removal will thus have no effect on the list that you're enumerating. In your case, that might look like this:
Dim panels = pb.Controls.
OfType(Of Panel)().
Where(Function(pnl) pnl.Name.EndsWith("|A") OrElse
pnl.Name.EndsWith("|B")).
ToArray()
For Each pnl In panels
pnl.Dispose()
Next
Calliing Dispose
will remove the control from its parent and properly dispose it. If you just call Remove
then the control is not disposed. Unless you intend to reuse the control, that's bad.