Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   как из TreeView с произвольной глубиной сформировать таблицу (http://forum.oszone.net/showthread.php?t=274291)

nastr 19-12-2013 14:13 2274901

как из TreeView с произвольной глубиной сформировать таблицу
 
Есть TreeView окно, при запуске приложения оно пустое, я набросал код для заполнения parent и child ветвей, глубина может быть произвольной.
Задание: нужно хранить заполненное TreeView в базе данных и при повторном запуске ПО подгружать из БД.
Мое решение: в БД одна таблица, формата {ID, parantID, nodeName}. методы для загрузки и выгрузки в/из БД я написал, наверно представляю как из такой таблицы сформировать TreeView.
Вопрос: как из TreeView с произвольной глубиной (количеством элементов) сформировать таблицу формата {ID, parantID, nodeName}?

Iska 19-12-2013 14:21 2274906

Рекурсивно.

nastr 19-12-2013 14:28 2274913

я догадался, но реализовать это у меня не получается

Вот решение без рекурсии, но глубина обхода ограничена кодом.
Код:

public class Trees
    {
        public Trees()
        {
        }
        public Trees(int NoteID, int ParentNoteID, string NoteName)
        {
            this.NoteID = NoteID;
            this.ParentNoteID = ParentNoteID;
            this.NoteName = NoteName;
        }
        public int NoteID { get; private set; }
        public string NoteName { get; private set; }
        public int ParentNoteID { get; private set; }
    }
private void treeNode()
{
        List<Trees> l = new List<Trees>();
        foreach (TreeNode childChildNode in treeView1.Nodes)
        {
                l.Add(new Trees(1, 0, treeNode.Text));
                foreach (TreeNode childChildNode in treeNode.Nodes)
                    {
                        l.Add(new Trees(2, 1, treeNode.Text));
                        foreach (TreeNode c in childChildNode.Nodes)
                        {
                            l.Add(new Trees(3, 2, treeNode.Text));
                            //и так далее для обхода в глубину, а глубина должна быть произвольной
                        }
                    }
        }
}

Вот такой рекурсивный метод, но как еги применить к моей ситуации я пока не представляю.
Код:

private List<TreeNode> GetAllNodes(TreeNode Node)
        {
           
            List<TreeNode> list = new List<TreeNode>();
            list.Add(Node);
            foreach (TreeNode n in Node.Nodes)
                list.AddRange(GetAllNodes(n));
            return list;
        }


lxa85 19-12-2013 14:44 2274927

nastr, а тут не телепаты, чтобы ваш код знать ;)

nastr 19-12-2013 20:34 2275173

...

nastr 19-12-2013 23:29 2275291

Следующий код:
Код:

    public class Trees
    {
        public Trees()
        {
        }
        public Trees(int NoteID, int ParentNoteID, string NoteName)
        {
            this.NoteID = NoteID;
            this.ParentNoteID = ParentNoteID;
            this.NoteName = NoteName;
        }
        public int NoteID { get; private set; }
        public int ParentNoteID { get; private set; }
        public string NoteName { get; private set; }
    }
        private void saveButton_Click(object sender, EventArgs e)
        {
            int processed = 0;
            bool root = true;
            saveTreeNode(treeView1.Nodes, 0, ref processed, ref root);
            string str = String.Empty;
            foreach (Trees t in l)
                str += "\t" + t.NoteID + "\t" + t.ParentNoteID + "\t" + t.NoteName + Environment.NewLine;
            MessageBox.Show(str);
            str = String.Empty;
            l.Clear();
        }
        List<Trees> l = new List<Trees>();
        private void saveTreeNode(TreeNodeCollection nodes, int NoteID, ref int processed, ref bool root)
        {
            foreach (TreeNode node in nodes)
            {
                int ParentNoteID;
                if (root)
                {
                    ParentNoteID = -1;
                    root = false;
                }
                else
                    ParentNoteID = NoteID - 1;
                l.Add(new Trees(NoteID, ParentNoteID, node.Text));
                ++processed;
                saveTreeNode(node.Nodes, NoteID + 1, ref processed, ref root);
                root = true;
                NoteID = processed;
            }
        }

Выводит правильный результат только в случае линейного дерева, т.е.:
читать дальше »

/ 0 -1 parent
- 1 0 child
-- 2 1 child
-- 3 2 child
--- 4 3 child
/ 5 -1 parent
- 6 5 child
-- 7 6 child
--- 8 7 child

Но в случае не линейного дерева получается совсем не то что хотелось бы:
читать дальше »

/ 0 -1 parent
- 1 0 child
--2 1 child
--3 -1 child
- 4 -1 child
- 5 -1 child
/ 6 -1 parent
- 7 6 child
- 8 -1 child
- 9 -1 child

lxa85 20-12-2013 09:18 2275462

nastr, Насколько я понимаю древовидное описание, на основе {ID, parentID, NodeName}, не в первом, не во втором случае ответ не правильный.
Попробовал вчитаться в процедуру -- не понял.

Напишите на примере

Код:

Alpha
    Bravo       
    Charlie
    Delta       
        Echo
        Foxtrot
            Golf
                Hotel       
    India
        Juliet
    Kilo       
    Lima
Mike
    November
        Oscar
            Papa
        Quebec
            Romeo
        Sierra
        Tango
            Uniform
                Victor
            Whiskey
    X-ray
    Yankee
    Zulu


Кто кому родитель и кто кому ребенок.
Причем желательно в обе стороны, и желательно руками.
Структура -> Дерево.
Дерево -> Структура.

nastr 20-12-2013 13:16 2275594

Вот структура дерева
читать дальше »

/ 0 -1 parent
- 1 0 child
-- 2 1 child
-- 3 2 child
---4 3 child
/ 5 -1 parent
- 6 5 child
-- 7 6 child
---8 7 child

Equal to:

Alpha
-Bravo
--Charlie
---Delta
Mike
-November
--Oscar
---Papa
;
/ 0 -1 parent
- 1 0 child
--2 1 child
--3 -1 child
- 4 -1 child
- 5 -1 child
/ 6 -1 parent
- 7 6 child
- 8 -1 child
- 9 -1 child

Equal to:

Alpha
-Bravo
--Charlie
--Delta
-Echo
-Foxtrot
Mike
-November
-Oscar
-Whiskey

nastr 20-12-2013 13:50 2275611

возможно я изначально, концептуально не верно подошел к решению вопроса, возможно есть какой-то другой способ записать TreeView в БД, и потом загрузить из БД, нежели рекурсивный перебор всех ветвей для формирования таблицы и т.д.
В любом случае всем спасибо за помощь!

pva 20-12-2013 16:21 2275678

nastr, используй глобальный счётчик для создания новой ветки, сделай что-то вроде рекурсивного перебора всех веток
Так бы оно могло выглядеть на js:
Код:

var __id=0;
function genId() { return ++__id; }

function walk(root_id, root, text) {
  var kid_id=genId();
  WScript.Echo("INSERT INTO TAB1 (PARENT_ID, ID, TEXT) VALUES("+root_id+", "+kid_id+", '"+text+"');");
  for(var i in root) { walk(kid_id, root[i], i); }
}

data={
  floor1:{John:true, Marie:true},
  floor2:{maniac:true},
  floor3:{doctor:true, policeman:true}
};

walk("NULL", data, "thriller-house");


lxa85 20-12-2013 16:43 2275703

nastr,
Код:

private void saveTreeNode(TreeNodeCollection nodes, int NoteID, ref int processed, ref bool root)
        {
            foreach (TreeNode node in nodes)
            {
                int ParentNoteID;
                if (root)
                {
                    ParentNoteID = -1;
                    root = false;
                }
                else
                    ParentNoteID = NoteID - 1;
                l.Add(new Trees(NoteID, ParentNoteID, node.Text));
                ++processed;
                saveTreeNode(node.Nodes, NoteID + 1, ref processed, ref root);
                root = true;
                NoteID = processed;
            }
        }

Во первых мне не нравится вот это условие:
Код:

                int ParentNoteID;
                if (root) {
                    ParentNoteID = -1;
                    root = false;  }
                else  ParentNoteID = NoteID - 1;
....
                root = true;
                NoteID = processed;

В каждом вложении отсчет NodeID начинается сначала (с нули или с единицы).
поэтому NodeID = processed; мне не понятна.

Попробуйте для начала просто рекурсивную распечатку директорий сделать. Желательно с трассировкой.

nastr 20-12-2013 22:15 2275901

Цитата:

Цитата lxa85
В каждом вложении отсчет NodeID начинается сначала (с нули или с единицы).
поэтому NodeID = processed; мне не понятна.
Попробуйте для начала просто рекурсивную распечатку директорий сделать. Желательно с трассировкой. »

processed это ссылочная переменная, для того что бы В каждом вложении отсчет NodeID начинается не сначала, а продолжался с учётом предыдущего.

lxa85 21-12-2013 11:56 2276086

nastr,
Цитата:

Цитата nastr
processed это ссылочная переменная, для того что бы В каждом вложении отсчет NodeID начинается не сначала, а продолжался с учётом предыдущего. »

Зачем?
Это вызывает путаницу и лишнее усложнение кода, как для проверки, так и для понимания.
NodeID - должная вообще генерироваться автоматически, в процедуре записи дерева.
----
Шаг назад.
Процедура рекурсивного обхода дерева, и процедура записи дерева в линейную структуру -- это две отдельные процедуры!
Причем NodeID, как ключевое(уникальное) значение таблицы, должен считаться в процедуре записи

nastr 08-02-2014 21:34 2305635

The main question how to fully traverse/circumvent through all TreeView, for transforming Tree structure into a Table structure.
I want to note that the TreeView may contain a different number of branches, with different depths and different names.
I found a lot of information how to populate TreeView e.g. from DataTable, but I didn’t found information how to recursively traverse/circumvent a TreeView and populate/fill data e.g. to DataTable.

As sample I have following TreeView:
Aaron
-Baldwin
--Caleb
---Dale
--Earl
-Fabian
Gabriel
-Harold
-Ian

Necessary to convert the TreeView into e.g. DataTable:
id | Name | ParentId
--------------------------------
1 | Aaron | null
2 | Baldwin | 1
3 | Caleb | 2
4 | Dale | 3
5 | Earl | 2
6 | Fabian | 1
7 | Gabriel | null
8 | Harold | 7
9 | Ian | 7

nastr 12-02-2014 00:12 2307574

First of all i want tot thank you for your help, but similar code i already wrote by myself. Following code is work well:
Код:

        private void buttonSave_Click(object sender, EventArgs e)
        {
            TraverseTreeView(treeView1);
            string temp = String.Empty;
            foreach (string str in name)
                temp += str + Environment.NewLine;
            MessageBox.Show(temp);
            name.Clear();
        }
        List<string> name = new List<string>();
        private void TraverseTreeView(TreeView tview)
        {
            TreeNode temp = new TreeNode();
            for (int k = 0; k < tview.Nodes.Count; k++)
            {
                temp = tview.Nodes[k];
                name.Add(k+"\t"+temp.Text+"\tnull");
                for (int i = 0; i < temp.Nodes.Count; i++)
                    visitChildNodes(temp.Nodes[i]);
            }
        }
        private void visitChildNodes(TreeNode node)
        {
            name.Add(node.Text);
            for (int j = 0; j < node.Nodes.Count; j++)
                visitChildNodes(node.Nodes[j]);
        }

But there is still several things that I don't know how to realize:
1. Do not use global variable (List<string> name) for collecting result;
2. Correctly collect data perhaps in DataTable, in format "1 | Aaron | null".
Please chech code below, and fix mistaks:
Код:

private void buttonSave_Click(object sender, EventArgs e)
        {
            DataTable dt = new DataTable();
            dt = TraverseTreeView(treeView1);
            string temp = String.Empty;
            foreach (string str in dt)
                temp += str + Environment.NewLine;
            MessageBox.Show(temp);
            dt.Clear();
        }
        //List<string> name = new List<string>();
        private DataTable TraverseTreeView(TreeView tview)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(int));
            dt.Columns.Add("Name");
            dt.Columns.Add("ParentId", typeof(int));
            TreeNode temp = new TreeNode();
            for (int k = 0; k < tview.Nodes.Count; k++)
            {
                temp = tview.Nodes[k];
                dt.Rows.Add(k, temp.Text, null);
                //name.Add(temp.Text);
                for (int i = 0; i < temp.Nodes.Counst; i++)
                    dt.Rows.Add(i, visitChildNodes(temp.Nodes[i]).Text, i - 1);
            }
            return dt;
        }
        private DataTable visitChildNodes(TreeNode node)
        {
            //name.Add(node.Text);
            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(int));
            dt.Columns.Add("Name");
            dt.Columns.Add("ParentId", typeof(int));
            for(int j = 0; j < node.Nodes.Count; j++)
                dt.Rows.Add(j, visitChildNodes(node.Nodes[j]).Text, j - 1);
            return dt;
        }



Время: 09:34.

Время: 09:34.
© OSzone.net 2001-