我有一个ASP.net页面,其中包含一个动态更新的TreeView。我使用TreeNodeCollection遇到了一个问题,我无法弄清楚背后的原因。
以下代码是对问题的简化复制,当page_load事件触发使用根节点创建树视图控件时,则调用返回节点和子节点集合的函数。 A For Next循环遍历集合并将节点添加到根节点。然后将TreeView控件添加到页面中。以下示例按预期工作。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim treeView1 As New TreeView
treeView1.Nodes.Add(New TreeNode)
Dim nodeCollection As TreeNodeCollection = GetNodes()
For nodeIndex = 0 To nodeCollection.Count - 1
treeView1.Nodes(0).ChildNodes.Add(nodeCollection(nodeIndex))
Next
Me.Form.Controls.Add(treeView1)
End Sub
Function GetNodes() As TreeNodeCollection
Dim tnc As New TreeNodeCollection, tn As New TreeNode, sn As New TreeNode
For i = 0 To 4
tn = New TreeNode("Node" & i)
tn.ChildNodes.Add(New TreeNode("Subnode1"))
tn.ChildNodes.Add(New TreeNode("Subnode2"))
tn.ChildNodes.Add(New TreeNode("Subnode3"))
tnc.Add(tn)
Next
Return tnc
End Function
要复制问题,我使用Return tnc
更改了GetNodes()函数中的行Return tnc(1).ChildNodes
该函数仍然返回最初添加到Node1的三个子节点的有效TreeNodeCollection。
现在当代码开始遍历集合时,在For Next
循环中每次将一个节点添加到treeView1控件时,它都会从nodeCollection中删除???这随后混淆了下一个循环并且索引超出了范围错误。
为什么代码更改后是从集合中移出的节点,在初始示例中,nodeCollection会保留其所有项目。
修改
如果我将For Next循环更改为For Each循环,则异常略有不同,例如
For Each thisNode AS TreeNode In nodeCollection
treeView1.Nodes(0).ChildNodes.Add(thisNode)
Next
生成异常
收藏被修改;枚举操作可能无法执行。
当前节点(无论出于何种原因)从源集合移动到树视图时,哪种有意义。但是为什么在使用Return tnc
时不会发生这种情况?
答案 0 :(得分:2)
TreeNode
在给定时间点只能属于一个父TreeView
或父TreeNode
。当您使用属于一个“树”的TreeNode
并将其添加到另一个“树”时,它将自动从其之前的所有者中删除。
那么为什么返回外部节点集合而不是子节点的子集合之间的区别呢?我认为这种差异是因为外部集合没有所有者,因此没有所有者可以从中删除。对于子节点的子集合,它们都属于父节点,因此可以跟踪它们之间的关系。
这是一个显示差异的小图:
TreeNodeCollection
Node 1 (owner=<none>)
TreeNodeCollection
Node 1.1 (owner=Node 1)
Node 1.2 (owner=Node 1)
Node 1.3 (owner=Node 1)
Node 1.4 (owner=Node 1)
Node 2 (owner=<none>)
Node 3 (owner=<none>)
Node 4 (owner=<none>)
所以这个问题只会发生在拥有所有者的节点上。