Charles Petzold

Hierarchical TreeView Templates

February 17, 2006
New York City

There's no question in my mind that templates are one of the most powerful features in WPF. Although most template examples are in XAML, I've been experimenting with defining templates in code. lt's often weird, but I think I'm getting a better idea of what's going on behind the scenes.

The TreeView control displays hierarchical data. You can fill up a TreeView control all at once or incrementally, as the data is required. Filling up a TreeView all at once often involves a recursive function. Filling up a TreeView incrementally (which is necessary if you're using it to display a disk directory tree, for example) requires handling the Expanded event of TreeViewItem. With templates, however, it's possible to attach a class to the TreeViewItem that provides data for the TreeView as it's needed but without recursive functions or explicit event handling.

Here's a class I called DiskDirectory.cs. It's really just a wrapper around the DirectoryInfo class and I would have derived this class from DirectoryInfo were it not sealed. The DiskDirectory class requires a DirectoryInfo as a argument to its constructor, and it maps its own Name property to the same-named property in DirectoryInfo. The bulk of the class is dedicated to implementing the Subdirectories property of type List<DiskDirectory>. This is basically the GetDirectories method of DirectoryInfo but translated into a property that returns a collection.

What we want is for the TreeView to display objects of type DiskDirectory and for the ItemsSource of each TreeViewItem (that is, the children of the item) to be set from the Subdirectories property of DiskDirectory. The TemplateTheTree.csx (and rename to .cs) program shows how it's done. (This project also requires the TemplateTheTree.csproj project file.)

The window constructor of this program creates an object of type TreeView and sets it as the window's content. It then creates an object of type HierarchicalDataTemplate based on the DiskDirectory object, and the ItemsSource of this template is bound to the SubDirectories property of DiskDirectory. The VisualTree property of the template could be more elaborate, but I made it a simple TextBlock whose Text property is bound to the Name property of DiskDirectory. The template is now completed. The window constructor continues by creating a single object of type DiskDirectory for the system drive. (In a real-life application, you'd probably create DiskDirectory objects for all the drives.) This DiskDirectory object is used to set the Header and ItemsSource properties of a TreeViewItem, which also has it's ItemTemplate set to the HierarchicalDataTemplate created earlier.

Put that TreeViewItem into the TreeView and you're done. Each TreeViewItem uses a TextBlock to display the Name property of its associated DiskDirectory object, and uses the Subdirectories property of DiskDirectory to generate its child TreeViewItem objects. No recursive functions, no event handling, and no moving parts.