The spoiled boy, the treeview and the self referencing table
It's a great control for web design, and if your looking for a treeview control that is very simple to use, use theirs.
The other day I had to create a treeview that creates a hierarchical view based on a self referencing datatable. 5 months ago I'd have this done in a few seconds, however I soon found myself taking the IV of coffee from my arm and sucking on it with my mouth.
I spent a good chunk of time online looking for solutions. I found solutions that involved XML/XSLT, ninjas, recursion and trogdor. Though my first pick was ninjas (they'd get this job done before it was a job), I went with recursion because it was so much easier and I didn't have to muck with XML/XSLT (Big overhead there).
The Client Side
I had a few issues with the client side of the treeview. Albeit, this is the first time I've actually used the default ASP.NET Treeview. Once I got it working, I came up with errors upon errors when I wanted to expand/click on a tree node. For some reason, the scripts that were needed to run this treeview were not being loaded. As I did not need any clientside functionality (extra functionality), I removed it.
8 <asp:TreeView ID="tvWorkGroups" EnableClientScript="false" runat="server" ExpandDepth="FullyExpand" OnSelectedNodeChanged="tvWorkGroups_SelectedNodeChanged" />
The Server Side
I'm not a fan of DataSets. I never use them incase I need to, in this case I did. I needed to use a DataRelation object to relate the Parent/Child columns in my DataTable.
71 Workgroups workGroups = new Workgroups();
72 DataSet ds= new DataSet();
73 ds.Tables.Add(workGroups.GetWorkgroupsDataTable(((Website.BasePage)this.Page).AuthUser));
74 DataRelation dr = new DataRelation("parentChild", ds.Tables[0].Columns["WorkgroupID"], ds.Tables[0].Columns["ParentWorkgroupID"]);
75 ds.Relations.Add(dr);
76
Once I created the relation and added it to my DataSet, The rest was very straight forward.
77 foreach (DataRow r in ds.Tables[0].Rows)
78 {
79 if (r.IsNull("ParentWorkGroupID"))
80 {
81 TreeNode n = new TreeNode();
82 n.Text = r["Description"].ToString();
83 n.Value = r["WorkGroupID"].ToString();
84 n.Expand();
85
86 RecursivelyLoadTree(r, ref n);
87 tvWorkGroups.Nodes.Add(n);
88
89 }
90 }
91 ds.Dispose();
92 ds = null;
Starting at the first row, loop through each one. Each row you actually hit will want to go into your recursive function:
95 private void RecursivelyLoadTree(DataRow row, ref TreeNode node)
96 {
97 foreach (DataRow cr in row.GetChildRows("parentChild"))
98 {
99 TreeNode n= new TreeNode();
100 n.Text = cr["Description"].ToString();
101 n.Value = cr["WorkGroupID"].ToString();
102 n.Expand();
103
104 node.ChildNodes.Add(n);
105 RecursivelyLoadTree(cr, ref n);
106 }
107 }
You can see I passed the node as ref, this allows all the modifications and additions we do to this node to be used in our root function that initially called this. I'm also using the GetChildRows("") function. I've added a DataRelation.
At the end of the day I was able to get my TreeView up and running as well as talk to myself on the asp.net forums so it wasn't a total waste.