在类中编写一个快速子例程,在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
有什么想法吗?
答案 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
。
请注意,如果控件嵌套在另一个控件中,则代码将无效。