The first question that comes to mind is: have you searched CP and StackOverFlow and the MS docs for how to data bind to a TreeView ?
Second: Are you dealing with a case here where: the possible "depth of nesting" in the TreeView is #2 or #3 ?
My impression is that you describe a case where the TreeView itself has #n Root-level Nodes, each of which corresponds to a Row in the parent.Rows of your DataBase. The "Parent" of a Root Node is always "null."
So, when you mention "grandchild" I'm not sure if you have a potential node depth of #2 or #3.
Your code shows only one level of inner parsing of child nodes, giving you a maximum depth of #2, unless you are thinking that a "root node" does, in a sense, have a "virtual depth" of #1, in spite of its parent being "null."
The other possibility I can't evaluate here is whether you have arbitrary depths of nesting possible: clearly you say some nodes can have children, but others may not, but can there be nodes that have many levels of nesting, beyond #2, or #3. ?
In the absence of a successful data binding strategy: which, imho, is the solution of choice, you are going to need to write recursive code to populate the TreeView, if you do, indeed, intend to have Nodes nested at arbitrarily deep levels.
In your sample code there are several strange aspects to me:
1. where do 'child.rows come from: shouldn't they be derived from parent.rows each time through the outer loop ?
2. you are adding a root-level node: 'tn
a. but then, instead of adding the child nodes to 'tn, you adding them to the calculated parent of 'tn: if 'tn is a root node: its parent is 'null, and there's an error right there.
A little more clarity from you on what your DB structure is, and your exact intent, and I hope I can be more helpful. What exactly do 'parent.rows' and 'child.rows' refer to ?
Meanwhile, consider (as a "wild guess"):
treeView1.BeginUpdate();
foreach(DataRow r in parent.Rows)
{
tn = treeView1.Nodes.Add(r["ID"].ToString(), r["Parent"].ToString());
foreach(DataRow dr in ?)
{
tn.Nodes.Add(dr["Child"].ToString());
}
}
treeView1.EndUpdate();