VB.NET循环控制面板跳过控件

时间:2013-05-13 11:48:42

标签: vb.net winforms foreach controls

在类中编写一个快速子例程,在VB.NET中将控件从一个Panel移动到另一个,这看起来很简单:

Public Sub Move(ByRef OldPanel As System.Windows.Forms.Panel)
    Dim panelControl As System.Windows.Forms.Control
    For Each panelControl In OldPanel.Controls
        MessageBox.Show(panelControl.Name) 'Debugging
        OldPanel.Controls.Remove(panelControl) 'Fairly certain this line makes no difference
        NewPanel.Controls.Add(panelControl)
    Next
End Sub

问题是,它只移动了大约一半的控件。其他面板根本不会被循环拾取并保持绑定到OldPanel。我已经确认控件肯定是OldPanel的一部分(并且不仅仅是在它上面浮雕)。

例如,如果面板上有6个控件,MessageBox.Show(panelControl.Name)仅反馈其中3个控件,并且只有3个控件移动。这是......莫名其妙。

我在表单类_Load事件本身内部编写了一个类似的调试循环,这正确地选取了面板上的所有6个控件:

Dim panelControl As System.Windows.Forms.Control
For Each panelControl In Me.Panel1.Controls
    MessageBox.Show(panelControl.name)
Next

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

此类问题的常见解决方案是向后循环整个集合。然后,当您删除项目时,它不会影响您尚未看到的项目的索引:

Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        MoveControls(Panel1, Panel2)
    End Sub

    Public Sub MoveControls(ByVal OldPanel As Panel, ByVal NewPanel As Panel)
        Dim ctlCount As Integer = OldPanel.Controls.Count - 1
        For i As Integer = ctlCount To 0 Step -1
            NewPanel.Controls.Add(OldPanel.Controls(i))
        Next
    End Sub

End Class

答案 1 :(得分:1)

您正在更改集合,同时使用每个集合循环它;这就是要求麻烦:一旦foreach启动并获得了枚举器,枚举器就像在开始时一样绑定到集合。

解决此问题的一种方法是首先循环并收集要删除的控件列表。

然后循环列表并删除这些控件。

另一种方法是使用不创建枚举器的for

请注意,如果控件嵌套在另一个控件中,则代码将无效。