删除另一个面板内的面板

Delete Panel within inside another panel

我有一个面板,里面有 4 个面板。内部面板被命名为“XXXX | 1 | A”、“XXXX | 1 | B”、“XXXX | 1 | C”和“XXXX | 1 | D”,您可以在最后一个字符中看到它们的区别一封信。

在这种情况下,我想做的是始终只删除标识为 A 和 B 的面板。

这是我的代码。

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

如您所见,通过变量controls_number我知道里面有4个Panel,但是在进行排列时,它只读取了3个并且只删除了标识为B的Panel并且没有未到达面板 A.

你能解释一下为什么你不看这 4 个面板吗?我有什么想法可以完成所有 4 个步骤吗?

谢谢。

首先你不能用管道字符“|”重命名控件因为这是设计师不允许的。 但是在下面的示例中,我假设它是一个下划线字符“_”。 现在当你循环一个集合时,如果它在这个循环中改变了她的维度,你就会失去在新 length/dimension 之后的元素数量(你删除)。 因此,要做到这一点,您可以将逆循环(最大维度为 0)用作技巧,在这种情况下,其余元素始终在循环中 inside/present。

下面这段代码说明了我的意思。

    For i As Integer = pb.Controls.Count - 1 To 0 Step -1
        If pb.Controls(i).Name Like "*_A" OrElse pb.Controls(i).Name Like "*_B" Then
            pb.Controls.Remove(pb.Controls(i))
        End If
    Next

永远不要在使用 For Each 循环枚举列表时修改它。在这种情况和许多其他情况下,简单的解决方案是将您想要的项目提取到一个单独的列表中,然后循环遍历该列表,同时从原始列表中删除这些项目。因此,删除不会对您正在枚举的列表产生任何影响。在您的情况下,可能看起来像这样:

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

调用 Dispose 将从其父控件中删除控件并正确处置它。如果您只是调用 Remove 则控件不会被释放。除非您打算重用该控件,否则很糟糕。