Need help understanding .Net Collection behaviour for a TreeNodeCollection
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?
A TreeNode
can belong to only one parent TreeView
or parent TreeNode
at a given point in time. When you take a TreeNode
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:
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>)
So this issue would only happen with nodes that have owners.
精彩评论