Home > c# > Rendering Paths as a nested List

Rendering Paths as a nested List

February 4th, 2009 fbis Leave a comment Go to comments

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 &gt; 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>
Categories: c# Tags:
  1. No comments yet.
  1. No trackbacks yet.