需要帮助了解 TreeNodeCollection 的 .Net Collection 行为
我有一个 ASP.net 页面,其中包含动态更新的 TreeView。我在使用 TreeNodeCollection 时遇到了问题,我无法找出背后的原因。
以下代码是该问题的简化复制,当 page_load 事件触发时,使用根节点创建树视图控件,然后调用一个函数来返回节点和子节点的集合。 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
为了重现该问题,我将 GetNodes() 函数中的行 Return tnc
更改为 Return tnc(1).ChildNodes
该函数仍然返回三个子节点的有效 TreeNodeCollection最初添加到 Node1 中。
现在,当代码开始遍历集合时,在 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
时不会发生这种情况呢?
I have a ASP.net page that contains a TreeView that is updated dynamically. I have encountered a problem using the TreeNodeCollection that I can not figure out the reasons behind.
The following code is a much simplified replication of the issue, when the page_load event fires a treeview control is created with a root node, then a function is called that returns a collection of nodes and subnodes. A For Next loops traverses the collection and adds the nodes to the root node. The TreeView control is then added to the page. The example below works as I expected.
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
To replicate the problem I change the line Return tnc
in the GetNodes() function with Return tnc(1).ChildNodes
The function still returns a valid TreeNodeCollection of the three sub nodes that were initially added to Node1.
Now when the codes begins to traverse the collection, in the For Next
loop each time a node is added to treeView1 control it is removed from the nodeCollection??? This subsequently messes up for next loop and an Index was out of range error is thrown.
Why after the code change are nodes moved from the collection, when in the initial example the nodeCollection retains all its items.
EDIT
If I change the For Next loop to a For Each loop then the exception is slightly different e.g
For Each thisNode AS TreeNode In nodeCollection
treeView1.Nodes(0).ChildNodes.Add(thisNode)
Next
generates the exception
Collection was modified; enumeration operation may not execute.
Which kind of makes sense as the current node (for whatever reason) is being moved from the source collection to the treeview. But why doesn't this happen when Return tnc
is used?
在给定时间点,
TreeNode
只能属于一个父TreeView
或父TreeNode
。当您将属于一棵“树”的TreeNode
添加到另一棵“树”时,它将自动从其先前的所有者中删除。那么为什么返回外部节点集合与返回子节点的子集合之间存在不同呢?我相信造成这种差异的原因是外部集合没有所有者,因此它没有可以从中删除的所有者。对于子节点的子集合来说,它们都属于父节点,因此能够跟踪它们的关系。
这是一个显示差异的小图:
因此,这个问题只会发生在拥有所有者的节点上。
A
TreeNode
can belong to only one parentTreeView
or parentTreeNode
at a given point in time. When you take aTreeNode
that belongs to one "tree" and add it to another "tree", it will automatically be removed from its previous owner.So then why the different between returning the outer node collection as opposed to the child node's sub-collection? I believe this difference is caused because the outer collection has no owner, so it has no owner from which it can be removed. In the case of the child node's sub-collection they all belong to the parent node, so their relationship is able to be tracked.
Here's a little diagram to show the difference:
So this issue would only happen with nodes that have owners.