Determining the depth of a node within a TreeView control

Given a TreeNode somewhere within a TreeView control, a desktop System.Windows.Forms developer would query the TreeNode.Level property to determine the depth of the node within the tree as demonstrated below:

MessageBox.Show(
  String.Format("Depth of node: {0}",
    treeView1.SelectedNode.Level));

However as stated by the MSDN Documentation this property is not available on the .NET Compact Framework. This is because one of the techniques Microsoft has used to reduce the size of the .NET Compact Framework is to remove methods and properties from the Base Class Library when the same behaviour can be implemented with a couple of lines of code written by the user.

So although the .NET Compact Framework does not provide a TreeNode.Level property we can implement our own, but first we must come up with a suitable algorithm.

General algorithm
Given a node within the tree (represented by the TreeNode class) we can determine the node’s Parent by querying the Parent property. If we repeat this process we will eventually get to a node which has null for it’s parent. This node is called the root (or top) of the tree. If we count the number of nodes we walked over to reach this node we have calculated the depth (or level) of the node we started at. This algorithm is implementable within C#.

Diagram outlining algorithm to determine depth of a node within a tree

Pre C# v3 Implementation
The best we can do with C# version 1 or 2 is to replace calls to missing methods with calls to static helper methods we manually write. For example we could write the following helper class to replace the TreeNode.Level property.

namespace MyProject
{
  public static class Utils
  {
    public static int Level(TreeNode node)
    {
      int i = -1;
 
      // Walk up the tree until we find the
      // root of the tree, keeping count of
      // how many nodes we walk over in
      // the process
      while (node != null)
      {
        i++;
        node = node.Parent;
      }
 
      return i;
    }
  }
}

and make use of it as follows

MessageBox.Show(
  String.Format("Depth of node: {0}",
    Utils.Level(treeView1.SelectedNode)));

C# v3 Implementation
C# version 3 (first available with the .NET 3.5 framework release) introduces a language feature called extension methods. This is basically a compiler trick which allows us to call helper methods such as the one created above with a slightly different syntax, that makes it appear as if the new methods we define are part of the existing objects. Behind the scenes the compiler is simply rewriting our statements to use the old syntax.

To convert our helper method into an extension method we only need to convert the method prototype from

public static int Level(TreeNode node) { ... }

to

public static int Level(this TreeNode node) { ... }

The magical “this” keyword is enough to get the following syntax to work

MessageBox.Show(
  String.Format("Depth of node: {0}",
    treeView1.SelectedNode.Level()));

Notice how our new Level() method can be called as it it was a member of the TreeNode class. This is very close to the original syntax that a desktop developer would utilise. In this example ideally we would create an “extension property”, which would mean we could utilise identical syntax on both platforms, however C# v3 does not support extension properties, only extension methods.

Sample Application

[Download TreeNodeLevelExample.zip - 19KB]

A sample application is available for download. The application shows a simple tree view and allows the user to select different nodes within it. As different nodes are selected a label is updated to show the depth of the currently selected node.

There are two versions of the sample application. The first is designed for .NET CF 2.0 and uses the first technique demonstrated, while the second is for .NET CF 3.5 and demonstrates the cleaner extension method based syntax.

Daniel Moth among others have discussed various techniques to support cross compiling code across both the .NET Compact and Full desktop frameworks. Extension methods are another tool to add to the toolbox, allowing you to provide your own implementations for methods missing from the .NET Compact Framework without requiring code changes to your main application source code.

Is anyone aware of any discussions available online about why it was decided not to support extension properties (or events)? Is this something we can expect to see in C# version 4?

Leave a Reply