When building up a tree view that represents the directory structure of a file system, like the windows explorer, my first reaction was to use recursion to traverse the file system and build up a tree. I quickly found that doing something like that is a time consuming process, and required some optimization.

I came up with what I like to call the recursive command. Each Tree Node item on a tree view is bound to a command to execute. The command looks like this...

1 public interface ITreeNodeClickedCommand {
2       void Execute(ITreeNode node);
3   }

When the command is executed, the command gets an opportunity to modify the state of the tree node that was clicked. In this case I wanted to lazy load the sub directories of a node that was clicked. The command implementation looks like this...

 1 public interface IAddFoldersCommand : ITreeNodeClickedCommand {}
 2   
 3   public class AddFoldersCommand : IAddFoldersCommand {
 4       private readonly DirectoryInfo the_current_directory;
 5       private bool has_executed;
 6   
 7       public AddFoldersCommand(DirectoryInfo the_current_directory) {
 8           this.the_current_directory = the_current_directory;
 9       }
10   
11       public void Execute(ITreeNode node) {
12           if (!has_executed) {
13               foreach (var directory in the_current_directory.GetDirectories()) {
14                   node.Add(new TreeNodeItem(directory.Name, ApplicationIcons.Folder, new AddFoldersCommand(directory)));
15               }
16           }
17           has_executed = true;
18       }
19   }

This command is executed each time the tree node that it is bound too is clicked, but will only build up the child tree node items once. Each of the child tree nodes are bound to a new instance of the same command. Hence, what I like to call the recursive command.

recursive_command

For more information on the command pattern check out WikiPedia's write up.

*Update 11:30 am MST, Friday, August. 01, 2008

After a little more inspection, I realized I was doing nothing more than just visiting each tree node item on the demand. Visitors are known to be great for recursive structures.... so ix-nay on the ecursive-ray ommand-kay.

The revised version:

 1 public interface IAddFoldersToTreeVisitor : ITreeNodeVisitor
 2   {
 3   }
 4   
 5   public class AddFoldersToTreeVisitor : IAddFoldersToTreeVisitor
 6   {
 7       private readonly DirectoryInfo the_current_directory;
 8       private bool has_executed;
 9       private readonly IAddFilesToTreeVisitor add_files_visitor;
10       private readonly IAddFoldersCommandFactory factory;
11   
12       public AddFoldersToTreeVisitor(DirectoryInfo the_current_directory, IAddFoldersCommandFactory factory,
13                                      IAddFilesToTreeVisitor add_files_visitor)
14       {
15           this.the_current_directory = the_current_directory;
16           this.factory = factory;
17           this.add_files_visitor = add_files_visitor;
18       }
19   
20       public void Visit(ITreeNode node)
21       {
22           if (!has_executed)
23           {
24               foreach (var directory in the_current_directory.GetDirectories())
25               {
26                   node.Add(directory.Name, ApplicationIcons.Folder, factory.CreateFor(directory));
27               }
28               add_files_visitor.PreparedWith(the_current_directory);
29               add_files_visitor.Visit(node);
30           }
31           has_executed = true;
32       }
33   }

links

comments powered by Disqus