2010-02-24 3 views
2

Прежде всего, у нас есть всемогущий код!Проблема с ссылкой на TreeNodeCollection

List nodes = new List(); 
TreeNode Temp = new TreeNode(); 

TreeNodeCollection nodeList = treeViewTab4DirectoryTree.Nodes; 

while (nodeList.Count != 0) 
{ 
    Temp = nodeList[0]; 

    while (Temp.FirstNode != null) 
    { 
     Temp = Temp.FirstNode; 
    } 

    if (!nodes.Contains(Temp.FullPath)) 
    { 
     nodes.Add(Temp.Text); 
    } 

    nodeList.Remove(Temp); 
}

Теперь проблема: Я написал код выше с целью создания списка, содержащего текст из всех узлов в дереве. Это работает отлично. Проблема, с которой я сталкиваюсь, заключается в удалении узлов из моей переменной, которые они также удаляются из фактического списка. Вопрос в том, как я могу сделать копию списка узлов, чтобы я мог играть с ними, не входя в список ACTUAL. Как я могу сделать копию этого документа, просто не ссылаясь на него? Любая помощь будет оценена!

+0

FYI: В строке 2 вам не нужно создавать новый «TreeNode» - вы можете просто назначить эту переменную «null» для начала. –

+0

@Jon Спасибо.Я внес изменения в свой код – Adkins

+0

Является ли это стандартным WinForms TreeView? Разумеется, вы должны были использовать: Список nodes = new Список (); ? ... Также нет необходимости инициализировать «Temp»: вы можете просто использовать: TreeNode Temp; – BillW

ответ

2

Ваша проблема возникает из-за того, что «nodeList» является ссылкой на treeViewTab4DirectoryTree.Nodes, а не на его копию.

Решение полностью зависит от того, какой тип TreeNodeCollection вы используете (WinForms, ASP.net, что-то еще?), Так как вам нужно искать .Copy(), .Clone(),. ToArray() или аналогично, чтобы получить копию содержимого коллекции, а не ссылку на существующую коллекцию.

Если, например, вы используете asp.net и, таким образом System.Web.UI.WebControls.TreeNodeCollection, вы можете использовать метод .CopyTo таким образом, подобный этому:

TreeNode[] x = null; 
treeViewTab4DirectoryTree.Nodes.CopyTo(x, 0); 
+0

@ Роб, я попробовал ваш код, но компилятор сказал, что целевой массив не может быть нулевым, и он также не может быть не назначен. Есть ли способ сделать его динамичным? Будет ли список работать, если подпись для CopyTo специально вызывает массив? – Adkins

+1

@Adkins, вам, вероятно, придется инициализировать массив до его использования, тогда специфика этого будет ниже используемого типа TreeNode. По сути, мой ответ заключается в том, что вам нужно сделать * новую коллекцию для удаления элементов, а не удалять их из nodeList или treeViewTab4DirectoryTree.Nodes. Вместо этого у вас есть список , что вы ** добавляете ** узлы, которые хотите сохранить (или те, которые хотите удалить), вместо того, чтобы пытаться изменить существующую коллекцию? – Rob

+0

Я не могу неявно конвертировать между типами TreeNodeCollection и набором элементов TreeNode (? Huh?). Однако я могу пройти через TreeNodeCollection, добавив каждый из них в коллекцию TreeNode. Спасибо за указатели! – Adkins

2

Обновлено показать стека подход, основанный:

List<String> result = new List<String>(); 
Stack<IEnumerator> nodeColls = new Stack<IEnumerator>(); 
IEnumerator nodes = treeViewTab4DirectoryTree.Nodes.GetEnumerator(); 

nodeColls.Push(null); 

while (nodes != null) 
{ 
    while (nodes.MoveNext()) 
    { 
     result.add(nodes.Current.FullPath); 
     if (nodes.Current.FirstNode != null) 
     { 
      nodeColls.Push(nodes); 
      nodes = nodes.Current.Nodes.GetEnumerator(); 
     } 
    } 

    nodes = nodeColls.Pop(); 
} 

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

Я действительно думал, что исходный код (в вопросе) сделал это тоже, потому что я думал, что «Удалить» фактически удалит узел верхнего уровня после поиска первого листового узла под ним; но вместо этого он пытается удалить листовой узел из коллекции узлов верхнего уровня и просто игнорирует его, если он не может его найти.

Оригинальный пост, неработающий код

Прежде всего, почему вы должны удалить элементы из списка?

List<string> nodes = new List<string>(); 

foreach (TreeNode tn in treeViewTab4DirectoryTree.Nodes) 
{ 
    TreeNode temp = tn; 

    while (Temp.FirstNode != null) 
    { 
     Temp = Temp.FirstNode; 
    } 

    if (!nodes.Contains(Temp.FullPath)) 
    { 
     nodes.Add(Temp.Text); 
    } 
} 

Чтобы ответить на конкретный вопрос, если предположить, что коллекция узлов реализует IEnumerable, использование:

List<TreeNode> nodeList = new List<TreeNode>(treeViewTab4DirectoryTree.Nodes); 

Если вы решили придерживаться своего цикла в то время, вы можете сохранить instatiation путем изменения

TreeNode Temp = new TreeNode(); 

в

TreeNode Temp = null; 

... вы никогда не используете объект, который вы создаете, по крайней мере, в той части кода, который вы указали.

+0

@Arne Я попытался создать список, как вы сказали, но получил ошибку, что конструктор получил неправильный параметр. Я проверил его, и он получает именно то, что он хочет, но я не могу избавиться от сообщения об ошибке. – Adkins

+0

@ Арне также цикл, который вы предложили, возвращает только первый ребенок каждого из корневых узлов. Вот почему я удалял элементы. Когда я полностью прошел через один из них, я удалил его. Когда не было больше, чтобы удалить, я был закончен. – Adkins

+0

@Arne Standard WinForms TreeNodeCollection не IEnumerable: для обсуждения того, как сделать его совместимым с IEnumerable и примерным кодом для итерации с помощью Linq: http://stackoverflow.com/questions/1815497/enumerating-collections-that-are-not-inherently -enumerable – BillW