VB.NET通过面板中的控件循环跳过控件

VB.NET通过面板中的控件循环跳过控件,vb.net,winforms,foreach,controls,Vb.net,Winforms,Foreach,Controls,在类中编写了一个快速子例程,用于在VB.NET中将控件从一个面板移动到另一个,这似乎很简单: 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

在类中编写了一个快速子例程,用于在VB.NET中将控件从一个
面板移动到另一个
,这似乎很简单:

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
。我已经验证过,这些控件肯定是
旧面板的一部分(而不仅仅是在其上方视觉浮动)

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

我在窗体类
\u Load
事件本身中编写了一个类似的调试循环,它正确地拾取了面板上的所有6个控件:

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

有什么想法吗?

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

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

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

另一种方法是对
使用
,它不创建枚举数


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

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

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

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

另一种方法是对
使用
,它不创建枚举数


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

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

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

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

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

您在循环过程中更改集合;那是自找麻烦。啊哈,接得好。事实上,很可能就是这样。你正在改变集合,同时在其中循环;那是自找麻烦。啊哈,接得好。事实上,很可能就是这样。干杯。我会在5分钟内记下答案。您是否可以展开“如果一个控件嵌套在另一个控件中,您的代码将无法工作”?移动“父”控件不也会移动其子控件吗?是的,会移动,但是如果不想移动父控件,也要移动子控件,则必须循环到每个控件的子控件。这有意义吗?啊,我明白了。这超出了此函数的范围(它应该只是移动所有内容),但很高兴知道,谢谢。我认为编译器在尝试更改For Each循环中的集合时出错。hmm@TomF-应该是,但不是。也许控件集合比它应该的更宽容。分类,干杯。我会在5分钟内记下答案。您是否可以展开“如果一个控件嵌套在另一个控件中,您的代码将无法工作”?移动“父”控件不也会移动其子控件吗?是的,会移动,但是如果不想移动父控件,也要移动子控件,则必须循环到每个控件的子控件。这有意义吗?啊,我明白了。这超出了此函数的范围(它应该只是移动所有内容),但很高兴知道,谢谢。我认为编译器在尝试更改For Each循环中的集合时出错。hmm@TomF-应该是,但不是。也许控件集合比它应该的更宽容。