Нужна помощь в понимании поведения .Net Collection для TreeNodeCollection - PullRequest
3 голосов
/ 15 июня 2011

У меня есть страница 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

Чтобы воспроизвести проблему, я изменяю строку Return tnc в функции GetNodes () с помощью Return tnc(1).ChildNodes

Функция по-прежнему возвращает действительную коллекцию TreeNodeCollection трех подузлов, которые были первоначально добавлены в Node1.

Теперь, когда коды начинают проходить по коллекции, в цикле For Next каждый раз, когда узел добавляется в элемент управления treeView1, он удаляется из nodeCollection ??? Это впоследствии приводит к ошибкам в следующем цикле, и в результате выхода индекса за пределы диапазона выдается ошибка.

Почему после изменения кода узлы перемещаются из коллекции, когда в начальном примере nodeCollection сохраняет все свои элементы.

EDIT

Если я изменю цикл For Next на цикл For Each, то исключение немного отличается, например

For Each thisNode AS TreeNode In nodeCollection
    treeView1.Nodes(0).ChildNodes.Add(thisNode)
Next

генерирует исключение

Коллекция была изменена; операция перечисления может не выполняться.

Какой тип имеет смысл, поскольку текущий узел (по любой причине) перемещается из исходной коллекции в древовидную структуру. Но почему этого не происходит, когда используется Return tnc?

1 Ответ

2 голосов
/ 17 июня 2011

A 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>)

Так что эта проблема может возникнуть только с узлами, у которых есть владельцы.

...