Rendering Paths as a nested List
Keeping tree data in a database can be a nightmare. There are a number of techniques to achieve it but they are all either unwieldy on the sql side (multiple joins) or on the data side (binary trees). I needed an easy way to render a tree out in a single read from the db.
I achieved this by just having a path field in the table, ordering by it and then dumping it out with the following routine. Needs more work but ok for the mo
Would need to change to writer instead of StringBuilder and I need to sort out the items that appear at the top (would appear under the folders in a treeview)
string LastPath = null; int LastPathDepth = 0; int ulDepth = 0; int PathDepth = 0; while (dr.Read()) { //If its the first time in we need to set the lastPath Info if (LastPath == null) { LastPath = dr["Path"].ToString(); LastPathDepth = Convert.ToInt32(dr["Depth"]); } //get data into variables to save typing string thisPath = dr["Path"].ToString(); PathDepth = Convert.ToInt32(dr["Depth"]); //is this path in the same root parent bool SameRoot = thisPath.StartsWith(GetRoot(LastPath)); if (LastPath != thisPath) { if (!SameRoot) { //different root so need to back up to create new trunk sb.Insert(sb.Length, " ", ulDepth - 1); ulDepth = 0; LastPathDepth = 0; LastPath = "/"; } //Are we shallower with this one? if (PathDepth < LastPathDepth) { //We are shallower so close the items up properly sb.Insert(sb.Length, " ", LastPathDepth - PathDepth); ulDepth -= LastPathDepth - PathDepth; sb.AppendLine(@" <li>" + GetLastFolder(thisPath) + @" <ul>"); ulDepth++; } //This path is going deeper if (PathDepth > LastPathDepth) //Going deeper { if (PathDepth - LastPathDepth == 1) { //just 1 deeper so add it sb.AppendLine(@" <li>" + GetLastFolder(thisPath) + @" <ul>"); } else { //have multiple folders so need to create them all string[] folders = thisPath.Replace(LastPath, "").Split('/'); foreach (string s in folders) { if (s != "") { sb.AppendLine(@" <li>" + s + @" <ul>"); ulDepth++; } } } ulDepth++; } //Same depth so close last ul/li and start a new one if (PathDepth == LastPathDepth) { sb.AppendLine(@"</ul> </li> <li>" + GetLastFolder(thisPath) + @" <ul>"); } LastPath = thisPath; LastPathDepth = PathDepth; } //Write out the item sb.AppendLine(@" <li>" + dr["Name"] + "</li> "); } //close li and uls to the last nested depth sb.Insert(sb.Length, "</ul> </li> ", (LastPath.Length - LastPath.Replace("/", "").Length)-1); sb.AppendLine("</ul> "); //containing url</li> </ul> </li>