Дерево C # дублирует каждый узел, когда я добавляю к нему - PullRequest
2 голосов
/ 06 мая 2011

Итак, в основном я занимаюсь созданием дерева задом наперед. Я начинаю с листьев, затем добавляю их родителей, потом их (в конце концов, это 3-х уровневое дерево).

У меня нет проблем с добавлением листьев (я запрашиваю базу данных, и для каждой записи создаю TNode (расширение класса TreeNode), а затем добавляю их в дерево). На этом шаге дублирования нет - дублирование происходит, когда я добавляю родителей листьев.

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

То, что делает программа, - это создание ДВУХ КОМПЛЕКТОВ каждого конечного узла ПОД КАЖДЫМ РОДИТЕЛЕМ, поэтому это выглядит так:

это не позволит мне опубликовать изображение, поэтому я попытаюсь нарисовать дерево в тексте: что-то вроде этого

    Part 1
       child 1-1
       child 1-2
       child 1-3
       child 1-1
       child 1-2
       child 1-3
    Part 2
       child 2-1
       child 2-2       
       child 2-1
       child 2-2  

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

Я также попытался сократить счетчик до 1, и он добавляет ОДНОГО родителя, и у него ОДИН потомок, который дублируется ....

В любом случае, код:

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

private void addLvl1Nodes() {

    int i = 0;
    TNode newNode = null;
    int count = tv_master.Nodes.Count;
    while (i < count) {
        TNode tn = (TNode)tv_master.Nodes[i];//get current node
            //if i = 0, then newNode has not been set, so make a new one!
            if ((i == 0)||
                (tn.Section != ((TNode)tv_master.Nodes[i-1]).Section )||
                (tn.Text.Substring(0, 1) != tv_master.Nodes[i - 1].Text.Substring(0, 1))){

                newNode = new TNode("");
                tv_master.Nodes.Add(newNode);
                switch (tn.Text.Substring(0, 1)) {
                    case "1": newNode.Text = "Part One"; break;
                    case "2": newNode.Text = "Part Two"; break;
                    case "3": newNode.Text = "Part Three"; break;
                }

                newNode.Section = tn.Section;

            }
        newNode.Nodes.Add(tn);

        i++;
    }
}

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

Большое спасибо!

+++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++

Для тех, кто сталкивается с подобной проблемой, вот окончательная копия моего кода, работающая, как ожидается, сейчас:)

private void addLvl1Nodes() {

            TNode newNode = null;

            List<TNode> nodes = tv_master.Nodes.Cast<TNode>().ToList();
            tv_master.Nodes.Clear();

            for(int i = 0; i<nodes.Count; i++){
                TNode tn = nodes[i];

                if ((i == 0) ||
                    (tn.Section != nodes[i-1].Section) ||
                    (tn.Text[0] != nodes[i-1].Text[0])) {

                    newNode = new TNode("");
                    tv_master.Nodes.Add(newNode);
                    switch (tn.Text[0]) {
                        case '1': newNode.Text = "Part One"; break;
                        case '2': newNode.Text = "Part Two"; break;
                        case '3': newNode.Text = "Part Three"; break;
                    }

                    newNode.Section = tn.Section;

                }

                newNode.Nodes.Add(tn);

            }
        }

Ответы [ 3 ]

5 голосов
/ 06 мая 2011

Похоже, вам может потребоваться удалить tn из его старого родителя, прежде чем сделать этот вызов:

  newNode.Nodes.Add(tn);

В противном случае у вас фактически не будет двух отдельных экземпляров tn (дочернего узла), но он будет отображаться в иерархии более одного раза. (Однажды под tv_master напрямую, однажды под недавно созданным узлом.)

Возможно, имеет смысл просто хранить два отдельных списка (или дерева) узлов. Один для хранения вновь созданных родительских узлов, а другой для конечных узлов. Тогда вы можете присоединиться ко всему в конце. Может быть, начать свой цикл так:

List<TNode> listLeafNodes = new List<TNode>(tv_master.Nodes);
tv_master.Nodes.Clear();
for( int i=0; i<listLeafNodes.Count; ++i )
{
...
}

Конечно, я не уверен, какой класс вы используете для TNode и tv_master. Интерфейс TNode, который я видел в MSDN, похоже, не имеет атрибута .Nodes. Также, по-видимому, есть как минимум 3 разных класса TreeView. Полностью квалифицированные имена классов для TNode и определение tv_master могут помочь нам лучше понять вещи.

2 голосов
/ 06 мая 2011

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

Чтобы добавить к их ответу,причина, по которой ваши начальные узлы также «перемещаются» за пределы корня, заключается в том, что метод TreeNodeCollection.Add не только добавляет узел в его внутренний массив, но также изменяет частное поле parent узла, чтобы указывать на его нового родителя.

Таким образом, на каждый из начальных узлов ссылаются из двух мест в вашем дереве (корень и 1-й дочерний узел), но его свойство Parent позволяет отображать обе ссылки под его родительским узлом.

1 голос
/ 06 мая 2011

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

Вы должны удалить дочерние элементы из коллекции, которые уже были обработаны.Но имейте в виду, что при этом ваше выражение в цикле while должно измениться.

Более того, вы можете упростить следующую строку

tn.Text.Substring(0, 1)

вот так

tn.Text[0]

Это также относится к сравнению первых символов позже в примере кода.

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