I'm really new at this C#. I'm not sure I'm understanding your
description. It sounds like it will populate a table in a Hierarchy
order. I am not understanding how this populates a treeview? I tried
writing some pseudocode but was completely lost. Could you provide a
little more detail for this novice.
Thanks
> Well, the one I originally stated would work fine. If you select the
>data in the order you specified, then you can do the following:
[quoted text clipped - 82 lines]
>>>> 18 16 2 15.16.18
>>>> 17 15 1 15.17
Hi,
Isn't there a problem here with child 15?
It has two entries in the data and is self referential.
I assume it is a typo although the heirarchy makes it look
intentional. A way of declaring a leaf node?
Anyway, stepping through Nicholas's logic.
He is suggesting a dictionary of nodes.
Each node has a child node collection.
i.e. each node is a tree in itself.
So
Step 1
Create a node. Attach your first row of data to it as a payload.
You can use the tag property for this.
Get the child value of this row of data from the data and use it as
the key for your dictionary entry.
Your dictionary will be keyed on an integer and its value will be a
treenode (System.Collections.Generics.Dictionary)
So...
treenode t = new treenode();
dictionary(<int>,<treenode>) d = new dictionary(<int>,<treenode>) ();
t.tag = myfirstdataobject //be it a string made from the data or a
class with the data in it. Up to you what you want to hang on the
tree.
d.add(1,t); in goes the first node
Now the next step is
make a new treenode say t1 and attach the second row of data to it.
Get its parent id from the data.
Ask the dictionary if it has the parent.
Seeing the parent id of the second data row is 1 then yes the
dictionary has it.
Add t1 to the node collection of t. other wise just add t1 to the
dictionary
if (d.containskey(1))
d[1].nodes.add(t1); //We are adding t1 into the nodes
collection of its parent
//now we stick t1 into the dictionary.
d.add(2,t1); //The key is two because that is the value retrieved from
your data, not because this is the second entry.
This process will work until you get to the second data row with 15 as
a child id. This will break the dictionary when you try to add it.
Don't know what you do here. Depends on the meaning of the data as to
what your options are.
you will only need a single pass with your perfectly sorted data.
but with unsorted data a number of passes would be necessary.
Once you have all of your nodes processed in the dictionary hang them
on your treeview.
To get your nodes from the dictionary to the tree you need to clone
the root nodes and add them to the treeview nodes collection.
as per this snippet where I have represented your data with class
myDummyload
private void BuildTree()
{
myDummyload dl1 = new myDummyload(1, 0);//childid,parentid
myDummyload dl2 = new myDummyload(2, 1);
List<myDummyload> myDataCollection = new
List<myDummyload>();
myDataCollection.Add(dl1);
myDataCollection.Add(dl2);
Dictionary<Int32,TreeNode> d = new
Dictionary<Int32,TreeNode>();
IEnumerator<myDummyload> en =
myDataCollection.GetEnumerator();
while (en.MoveNext())
{
TreeNode t = new TreeNode("I am node " +
en.Current.ChildId.ToString());
t.Tag = en.Current;
if (d.ContainsKey(((myDummyload)t.Tag).ParentId))
d[((myDummyload)t.Tag).ParentId].Nodes.Add(t);
d.Add(((myDummyload)t.Tag).ChildId, t);
}
IEnumerator<TreeNode> en1 = d.Values.GetEnumerator();
while (en1.MoveNext())
if (en1.Current.Parent == null)
this.treeView1.Nodes.Add((TreeNode)en1.Current.Clone());
}
Once you exit this code your treeview should be displaying your nodes
hth
bob
>I'm really new at this C#. I'm not sure I'm understanding your
>description. It sounds like it will populate a table in a Hierarchy
[quoted text clipped - 90 lines]
>>>>> 18 16 2 15.16.18
>>>>> 17 15 1 15.17
xmail123@yahoo.com - 17 Oct 2007 18:52 GMT
Bob thank you very much for your help and input.
My data will always be sorted as shown in the sample. I was hoping
that would make things easer.
15 is a parent and a child of itself. This is a case where, for
example, a business is a part of a group. Say a purchasing group.
And that same business is the headquarters for the purchasing group.
If the intent is to depict the purchasing group (which is what I have
to do) you end up with
15 Null - root tree node, purchasing group HQ
15 15 - member of purchasing group
16 15 - member of purchasing group
Etc.
I looked through the information you provided. I have a handle on
most of it. But the show stopper is not being able to handel the
child = parent data condition.
Prior to receiving your post I found nthis approach.
Building a dynamic Tree
http://www.codeproject.com/useritems/Dynamic_TreeView.asp?df=100&forumid=462426&
exp=0&select=2242832
I believe it will populate the treeview even with the child = parent
data condition. Please look at the code and tell me if you think I am
correct.
The problem is it uses the Info column to get the ID and I think it
will only accomidate the one root tree node. I am thinking it can be
tweeked to work with my data. But being a novis I am not sure how to
accomplish this.
Your description of the approach you suggested was very clear. If I
am correct and this will work can you give me some pointers on how to
modify this to work with my data?
namespace DynamicTree
{
public partial class Form1 : Form
{
DataTable tbl;
DataColumn col;
public Form1()
{
InitializeComponent();
InitTable();
initTableData();
}
private void InitTable()
{
tbl = new DataTable();
col = new DataColumn("ID");
tbl.Columns.Add(col);
col = new DataColumn("PID");
tbl.Columns.Add(col);
col = new DataColumn("Info");
tbl.Columns.Add(col);
tbl.AcceptChanges();
}
private void initTableData()
{
DataRow r;
r = tbl.NewRow();
r["ID"] = "0";
r["PID"] = "-1";
r["Info"] = "Root";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "1";
r["PID"] = "0";
r["Info"] = "Menu1";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "10";
r["PID"] = "0";
r["Info"] = "Menu10";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "2";
r["PID"] = "0";
r["Info"] = "Menu2";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "3";
r["PID"] = "0";
r["Info"] = "Menu3";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "4";
r["PID"] = "1";
r["Info"] = "Menu4";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "5";
r["PID"] = "4";
r["Info"] = "Menu5";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "6";
r["PID"] = "5";
r["Info"] = "Menu6";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "7";
r["PID"] = "2";
r["Info"] = "Menu7";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "11";
r["PID"] = "6";
r["Info"] = "Menu11";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "8";
r["PID"] = "10";
r["Info"] = "Menu8";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "9";
r["PID"] = "3";
r["Info"] = "Menu9";
tbl.Rows.Add(r);
r = tbl.NewRow();
r["ID"] = "12";
r["PID"] = "7";
r["Info"] = "Menu12";
tbl.Rows.Add(r);
}
private void Form1_Load(object sender, EventArgs e)
{
TreeNode r = new TreeNode();
r.Text = "Root";
initTreeView(r);
tree.Nodes.Add(r);
tree.ExpandAll();
}
private void initTreeView(TreeNode N)
{
DataTable temp = new DataTable();
col = new DataColumn("ID");
temp.Columns.Add(col);
col = new DataColumn("PID");
temp.Columns.Add(col);
col = new DataColumn("Info");
temp.Columns.Add(col);
temp.AcceptChanges();
string id = getID(N);
foreach (DataRow r1 in tbl.Rows)
{
if (r1["PID"].ToString() == id)
{
DataRow r2 = temp.NewRow();
r2["ID"] = r1["ID"].ToString();
r2["PID"] = r1["PID"].ToString();
r2["Info"] = r1["Info"].ToString();
temp.Rows.Add(r2);
temp.AcceptChanges();
}
}
foreach(DataRow r3 in temp.Rows)
{
TreeNode tn = new TreeNode();
tn.Text = r3["Info"].ToString();
initTreeView(tn);
N.Nodes.Add(tn);
}
}
private string getID(TreeNode N)
{
foreach (DataRow r in tbl.Rows)
{
if (r["Info"].ToString() == N.Text)
return r["ID"].ToString();
}
return "";
}
}
}
>Hi,
>Isn't there a problem here with child 15?
[quoted text clipped - 186 lines]
>>>>>> 18 16 2 15.16.18
>>>>>> 17 15 1 15.17
bob - 18 Oct 2007 02:04 GMT
Hi,
Haven't got time to go any deeper with this at present.
I would prefer to stay with Nicholas's logic, it is compact and
maintanable.
First point is that it is not the self referentiality (such a word?)
that is the killer but the fact that child id is not unique.
So we need to ditch or disguise the second ClassId 15 record.
My gut reaction is to separate the attributes of your data from the
position in the tree and to ditch the second record.
i.e.
Suck the data into a collection of data classes similar to myDummyLoad
say myData, one instance for each row.
MyData would have a boolean property PurchasingGroup
As you attempt to load each treenode into the dictionary ask an
additional question. "Is this myData.ChildId already present in the
keys list?"
If it is then check to see if the parentId and child id of the
canditate data is the same i.e. PurchasingGroup is true
If the answer is yes then set the PurchasingGroup property of the one
that is already in the dictionary to true. And throw the canditate in
the bin
If the answer is no then you have an error as all Purchasing Groups
are self referential.
hth
Bob
>Bob thank you very much for your help and input.
>
[quoted text clipped - 393 lines]
>>>>>>> 18 16 2 15.16.18
>>>>>>> 17 15 1 15.17
xmail123@yahoo.com - 18 Oct 2007 15:43 GMT
Thanks for the input. I will work with it and see what i can do.
>Hi,
>Haven't got time to go any deeper with this at present.
[quoted text clipped - 423 lines]
>>>>>>>> 18 16 2 15.16.18
>>>>>>>> 17 15 1 15.17