1

Written a quick subroutine in a class to move controls from one Panel to another in VB.NET, which seemed simple enough:

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

The problem is, it only moves about half the controls. The other panels aren't picked up by the loop at all and remain bound to OldPanel. I have verified that the controls are definitely part of the OldPanel (and not just visually floated above it).

For example, if there are 6 controls on the panel, MessageBox.Show(panelControl.Name) only feeds back 3 of them, and only those 3 controls move. This is... baffling.

I wrote a similar debugging loop inside the form class _Load event itself and this correctly picks up all 6 controls on the panel:

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

Any ideas?

4

2 回答 2

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
于 2013-05-13T12:37:04.353 回答
1

您正在更改集合,同时使用 for each 循环它;这是自找麻烦:一旦启动 foreach 并获取枚举器,枚举器就会像开始时一样与集合绑定。

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

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

另一种方法是使用forwhich 不会创建枚举器。

请注意,如果控件嵌套在另一个控件中,您的代码将不起作用。

于 2013-05-13T11:58:06.083 回答