I am building up a basic folder tree with a list of strings in the form /root/node/node/node. Here is the basic algorithm I am using currently to build this collection and fill in my TreeGridView
:
// This method gets the list of folders and leaves, then trims out any folder paths
// that are already encompassed in a larger folder path, the idea is that it causes
// less work when adding the actual tree nodes (I may be wrong in this assumption)
List<string> BuildFinalList()
{
// This list is a collection of root folder paths and leaf folder names
// i.e. pair("/root/node/node", "node"), pair("/root/node", "node)
List<KeyValuePair<string, string>> folders = GetListOfFolders();
var paths = new List<string>();
foreach(var folder in folders)
{
var leaf = folder.Value;
var root = folder.Key;
paths.Add(string.Concat(root, "/", leaf);
}
paths.Sort(_INVERSE_LENGTH_COMPARE); // this sorts the list longest to shortest
// Iterate the computed paths from longest to shortest, if a path is not
// encompassed by an existing path in the final list, add it to the
// final list, otherwise just move to the next path
var finalList = new List<string>();
foreach(var path in paths)
{
bool found = false;
foreach(var item in finalList)
{
if (item.StartsWith(path, StringComparison.Ordinal))
{
found = true;
break;
}
}
if (!found)
{
finalList.Add(path);
}
}
return finalList;
}
Once I have the final list built, I then add the nodes to the tree (for simplification, I have removed the calls to end update and begin update of the tree that contains the root node):
void FillTreeNodes(TreeNode root)
{
var rootText = root.Text;
var rootTextLength = rootText.Length;
var nodeStrings = BuildFinalList();
foreach(var nodeString in nodeStrings)
{
var roots = nodeString.Split(new char[] { '/' },
StringSplitOptions.RemoveEmptyEntries);
// The initial parent is the root node
var parentNode = root;
var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength);
for(int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
// Build the node name
var parentName = roots[rootIndex];
sb.Append("/");
sb.Append(parentName);
var nodeName = sb.ToString();
// Search for the node
var index = parentNode.Nodes.IndexOfKey(nodeName);
if (index == -1)
{
// Node was not found, add it
var temp = new TreeNode(parentName, 1, 1);
temp.Name = nodeName;
parentNode.Nodes.Add(temp);
parentNode = temp;
}
else
{
// Node was found, set that as parent and continue
parentNode = parentNode.Nodes[index];
}
}
}
}