как из TreeView с произвольной глубиной сформировать таблицу
Есть TreeView окно, при запуске приложения оно пустое, я набросал код для заполнения parent и child ветвей, глубина может быть произвольной.
Задание: нужно хранить заполненное TreeView в базе данных и при повторном запуске ПО подгружать из БД.
Мое решение: в БД одна таблица, формата {ID, parantID, nodeName}. методы для загрузки и выгрузки в/из БД я написал, наверно представляю как из такой таблицы сформировать TreeView.
Вопрос: как из TreeView с произвольной глубиной (количеством элементов) сформировать таблицу формата {ID, parantID, nodeName}?
|
я догадался, но реализовать это у меня не получается
Вот решение без рекурсии, но глубина обхода ограничена кодом.
Код:
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;
}
|
nastr, а тут не телепаты, чтобы ваш код знать ;)
|
Следующий код:
Код:
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
|
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
Кто кому родитель и кто кому ребенок.
Причем желательно в обе стороны, и желательно руками.
Структура -> Дерево.
Дерево -> Структура.
|
Вот структура дерева
читать дальше »
/ 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
|
возможно я изначально, концептуально не верно подошел к решению вопроса, возможно есть какой-то другой способ записать TreeView в БД, и потом загрузить из БД, нежели рекурсивный перебор всех ветвей для формирования таблицы и т.д.
В любом случае всем спасибо за помощь!
|
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");
|
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; мне не понятна.
Попробуйте для начала просто рекурсивную распечатку директорий сделать. Желательно с трассировкой.
|
Цитата:
Цитата lxa85
В каждом вложении отсчет NodeID начинается сначала (с нули или с единицы).
поэтому NodeID = processed; мне не понятна.
Попробуйте для начала просто рекурсивную распечатку директорий сделать. Желательно с трассировкой. »
|
processed это ссылочная переменная, для того что бы В каждом вложении отсчет NodeID начинается не сначала, а продолжался с учётом предыдущего.
|
nastr,
Цитата:
Цитата nastr
processed это ссылочная переменная, для того что бы В каждом вложении отсчет NodeID начинается не сначала, а продолжался с учётом предыдущего. »
|
Зачем?
Это вызывает путаницу и лишнее усложнение кода, как для проверки, так и для понимания.
NodeID - должная вообще генерироваться автоматически, в процедуре записи дерева.
----
Шаг назад.
Процедура рекурсивного обхода дерева, и процедура записи дерева в линейную структуру -- это две отдельные процедуры!
Причем NodeID, как ключевое(уникальное) значение таблицы, должен считаться в процедуре записи
|
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
|
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.
© OSzone.net 2001-