Introduction

This article explores how to use the ViewModel pattern to make it easier to work with the TreeView control in WPF. Along the way, we examine why people often have difficulty with the WPF TreeView, what a ViewModel is, and two demo applications that show how to combine a TreeView with a ViewModel. One of the demos shows how to create a searchable TreeView, the other demonstrates how to implement lazy-loading (a.k.a. load-on-demand).

Background of TreeView

The TreeView control in WPF has gained an undeserved bad reputation. Many people try to use it, and find it to be exceedingly difficult. The problem is that people often try to use it in the same way that one might code against the Windows Forms TreeView control. In order to leverage the extensive features of the WPF TreeView, you cannot use the same programming techniques as in Windows Forms. This is yet another example of how WPF requires you to shift mental gears to make use of the platform appropriately. We aren’t in Kansas anymore, Toto.

In Window Forms, it is very easy to use the TreeView control because it is dead simple. That simplicity arises from the fact that the Windows Forms TreeView is completely inflexible, offers no support for UI virtualization, offers zero possibility for visual customizations, and since it does not support data binding, it requires you to store data in its nodes. The WinForms TreeView is “good enough for government work”.

In contrast, the WPF TreeView is extremely flexible, inherently supports UI virtualization (i.e., TreeViewItems are created on-demand), allows for full visual customization, and has full support for data binding. Those excellent features come at a price. They make the control more complicated than the WinForms TreeView. Once you learn how to properly work with the WPF TreeView, those complexities disappear, and it is quite easy to leverage the full power of the control.

If you are curious to see some examples of how the WPF TreeView can be customized, check out this article and this article.

Background of ViewModel

Back in 2005, John Gossman blogged about the Model-View-ViewModel pattern that his team at Microsoft was using to create Expression Blend (then known as ‘Sparkle’). It is quite similar to Martin Fowler’s Presentation Model pattern, only it fills in the gap between the presentation model and the view with WPF’s rich data binding. After Dan Crevier wrote his fantastic DataModel-View-ViewModel series of blog posts, the (D)MVVM pattern started growing in popularity.

The (Data)Model-View-ViewModel pattern is similar to the classic Model-View-Presenter, except you have a model tailor-made for the View, called the ViewModel. The ViewModel contains all the UI-specific interfaces and properties necessary to make it easy to develop a user interface. The View binds to the ViewModel, and executes commands to request an action from it. The ViewModel, in turn, communicates with the Model, and tells it to update in response to user interaction.

This makes it easier to create a user interface (UI) for the application. The easier it is to slap a UI on an application, the easier it is for a technically challenged Visual Designer to create a beautiful UI in Blend. Also, the more loosely coupled the UI is to the application functionality, the more testable that functionality becomes. Who does not want a beautiful UI and a suite of clean, effective unit tests?

What Exactly Makes the TreeView so Difficult?

The TreeView is actually quite easy to work with, provided you use it the correct way. Using it the correct way, paradoxically, means not directly using it at all! Naturally, you will need to set properties and call the occasional method directly on a TreeView. That is inescapable, and there’s nothing wrong with doing it. However, if you find yourself getting deep into the guts of the control, then you are probably not taking the best approach. If your TreeView is data bound and you find yourself trying to walk up and down the items programmatically, then you are not doing things the right way. If you find yourself hooking the ItemContainerGenerator’s StatusChanged event so that you can access a TreeViewItem’s child items when they are eventually created, you are way off track! Trust me; it does not have to be so ugly and difficult. There is a better way!

The fundamental problem with treating the WPF TreeView like the WinForms TreeView is, as I mentioned previously, that they are very different controls. The WPF TreeView allows you to generate its items via data binding. This means that it will create the TreeViewItems for you. Since TreeViewItems are being generated by the control, instead of by you, it is not guaranteed that a data object’s corresponding TreeViewItem exists when you need it. You must ask the TreeView’s ItemContainerGenerator if it has generated the TreeViewItem for you yet. If it has not, you must hook its StatusChanged event to be notified when it has created its child elements.

The fun does not stop there! If you want to get a TreeViewItem that is nested deep down in the tree, you must ask the item’s parent/owning TreeViewItem, not the TreeView control, if its ItemContainerGenerator has created the item. But, how can you get a reference to that parent TreeViewItem if its parent has not yet created it? What if the parent’s parent has not yet been generated either? And so on, and so on, and so on. It can be quite torturous.

As you can see, the WPF TreeView is a complicated beast. If you try to use it the wrong way, it will not be easy. Fortunately, if you use it the right way, it is a piece of cake. So, let’s see how to use it the right way…

ViewModel Comes to the Rescue

WPF is great because it practically requires you to separate an application’s data from the UI. All of the problems listed in the previous section derive from trying to go against the grain and treat the UI as a backing store. Once you stop treating the TreeView as a place to put data, and start treating it as a place to show data, everything starts working smoothly. This is where the idea of a ViewModel comes into play.

Rather than writing code that walks up and down the items in a TreeView, it is better to create a ViewModel to which the TreeView binds, and then write code that manipulates your ViewModel. Not only does this allow you to ignore the TreeView’s complexities, it also allows you to write code that can be easily unit tested. It is next to impossible to write meaningful unit tests for classes that have intimate dependencies on the runtime behavior of a TreeView, but it is easy to write unit tests for classes that know nothing about such nonsense.

Now, it is time to see how to implement these concepts.

The Demo Solution

This article is accompanied by two demo applications, available for download at the top of this page. The solution has two projects. The BusinessLib class library project contains simple domain classes, used as mere data transfer objects. It also contains a Database class that instantiates and returns those data transfer objects. The other project, TreeViewWithViewModelDemo, contains the sample applications. Those apps consume the objects returned by the BusinessLib assembly, and wrap them in a ViewModel before displaying them in a TreeView.

Here is a screenshot of the solution’s Solution Explorer:

Demo 1 – Family Tree with Text Search

The first demo application we will examine populates a TreeView with a family tree. It provides a search capability, made available to the user at the bottom of the UI. This demo can be seen in the screenshot below:

When the user types in some search text and presses Enter, or clicks the 'Find' button, the first matching item will display. Continuing the search will cycle through each matching item. All of that logic is in the ViewModel. Before getting too far into how the ViewModel works, let’s first examine the surrounding code. Here is the TextSearchDemoControl’s code-behind:

The constructor shows how we convert raw data objects into a ViewModel, and then set that as the DataContext of the UserControl. The Person class, which resides in the BusinessLib assembly, is quite simple:

PersonViewModel

Since the Person class is what the app’s data access layer returns, it is definitely not suited for consumption by the UI. Each Person object will eventually be wrapped by an instance of the PersonViewModel class, enabling it to have extended semantics, such as being expanded and selected. The FamilyTreeViewModel class, seen above, initiates the process of wrapping Person objects inside of PersonViewModel objects, as seen in that class’ constructor:

PersonViewModel has two kinds of members: those related to presentation, and those related to the state of a Person. The presentation properties are what a TreeViewItem will bind to, and the state properties are bound to by the content of a TreeViewItem. One of the presentation properties, IsSelected, is shown below:

This property has nothing to do with a “person”, but is simply a state used to synchronize the View with the ViewModel. Note that the property’s setter calls into an OnPropertyChanged method, which ends up raising the object’s PropertyChanged event. That event is the sole member of the INotifyPropertyChanged interface. INotifyPropertyChanged is a UI-specific interface, which is why the PersonViewModel class implements it, not the Person class.

A more interesting example of a presentation member on PersonViewModel is the IsExpanded property. This property easily solves the problem of ensuring that a data object’s corresponding TreeViewItem is expanded when necessary. Keep in mind, these types of issues can be extremely thorny and difficult to deal with when programming directly against the TreeView itself.

As I mentioned before, PersonViewModel also has properties related to the state of its underlying Person object. Here is an example:

publicstring Name
{
get { return _person.Name; }
}

The User Interface

The XAML for the TreeView that binds to the tree of PersonViewModels is quite straightforward. Note that the connection between the TreeViewItems and PersonViewModel objects lies in the control’s ItemContainerStyle:

Another piece of this demo’s UI is the search area. That area provides the user with a TextBox into which a search string is entered, and a 'Find' button to perform a search against the family tree. Here is the XAML for the search area:

When the user clicks the 'Find' button, the FamilyTreeViewModel’s SearchCommand executes. That command class is nested within FamilyTreeViewModel, but the property that exposes it to the View is public. That code is shown below:

If you are familiar with my WPF techniques and philosophies, you might be surprised to see that I am not using a routed command here. I normally prefer routed commands, for a multitude of reasons, but in this situation, it is cleaner and simpler to use a plain ICommand implementation instead. Note, be sure to read the comments in the CanExecuteChanged event declaration.

The search logic has absolutely no dependencies on TreeView or TreeViewItem. It is simply walking over the ViewModel objects and setting the ViewModel properties. Attempting to write this code directly against the TreeView API would be much more difficult and bug-prone. Here’s my search logic:

Demo 2 – Geographic Breakdown with Load-On-Demand

The next demo application populates a TreeView with information about various places within a country. It deals with three different types of objects: Region, State, and City. Each of those types has a corresponding presentation class, to which the TreeViewItems bind.

Each of the presentation classes derives from the TreeViewItemViewModel base class, which provides all of the presentation-specific functionality seen in the previous demo’s PersonViewModel class. In addition, the items in this demo are lazy-loaded, meaning that the program does not fetch an item’s children and add them to the object graph until the user tries to view them. You can see this demo in the screenshot below:

As I mentioned above, there are three separate data classes here, and each data class has an associated presentation class. All of those presentation classes derive from a TreeViewItemViewModel, described by this interface:

That constructor is simply loading up some data objects from the BusinessLib assembly, creating some UI-friendly wrappers out of them, and then letting the View bind to those wrappers. The View’s DataContext is set to an instance of this class:

The interesting code is in TreeViewItemViewModel. It is mostly just a copy of the presentation logic seen in the previous demo’s PersonViewModel, but with one interesting twist. TreeViewItemViewModel has built-in support for load-on-demand of child items. That logic exists in the class’ constructor and the setter of the IsExpanded property. The load-on-demand logic of TreeViewItemViewModel is seen below:

The actual work of loading an object’s child items is left for the subclasses to handle. They override the LoadChildren method to provide a type-specific implementation of loading child items. The RegionViewModel class, seen below, overrides this method to load State objects and create StateViewModel wrapper objects.

Conclusion

If you have ever battled with the WPF TreeView, perhaps this article has shed some light on an alternate way of using that control. Once you start going with the flow, and stop trying to swim upstream, WPF makes life very easy for you. The hard part is letting go of your hard-earned knowledge and skills, and to adopt radically different ways of approaching the same problems.

Special Thanks

I would like to thank Sacha Barber for encouraging me to write this article. He also gave me invaluable feedback and requests while I worked on the demo applications. If it wasn’t for him, I probably would have never written this article.

I have learned a lot from the article, but I am stumped on how to fill the Person List from a database in order to return new Person from the GetFamilyTree() method. I thought of building a linkedlist, but Person is a List and not a LinkedList. Are there any examples of how this is done?

First of all I commend the excellent work.
I had a problem when I want to add a child to an expanded node in a background worker. I tried adding a node to the Children list called a delegate through dispacher, but without success. Could you help me?
Best Regards.

First of all I want to thank you for such an easy explanation of MVVM and a very clarifying article about how to use TreeView, its excellent.

Testing your project I realized that you are not delaying the load of items on the LoadOnDemand implementation, which cause to load instantly the data, thus not allowing to see the "DummyChild", which in my case would have its text property set to: "Loading...".

The problems is that if I use a timer to delay the data load, the TreeViewItemViewModel full name is showed.

To solve that, a Text property can be added to TreeViewItemViewModel and the DummyChild can be instantiatet as:

Hi Josh,
I loved the way you handle the treeview with ViewModel. I have a question if you can answer it would be great since I am new to WPF world.
I have a situation that before I load the node I don't know how many child node it contains (it may have no child node or have multiple child nodes), when it has multiple child nodes, each of them may belongs to the different class objects. I can load the tree with procedure code but it seemed wrong. So how can I populate these trees using ViewModel or HierarchicalDataTemplate? Do you have any other suggestions?
Thanks a lot. Gordon

Lists are mutable, so the readonly List<t> is making sure that once Children is initialised, it continues to reference the same list; you can still add/remove/alter that list of children, but you cannot reassign it to look at another list.

I wish to open a separate window containing the TreeView from my application's main window. In the main window I have constructed a collection of custom objects that will serve as the data model. I am confusing myself mightily as I try to replace the call to the static Database.GetRegions() method in this excellent example with a reference to a variable contained in my main window. Any suggestions on how I might go about this?

First of all thank you for your MVVM articles at all, they are famous all over internet. I have one question - I make new application in WPF trying to follow MVVM pattern. I wish to implement generic user rights management based on values in database. My idea was to simply check elements during startup and enable/disable "features" which user can/can't click/read/write etc. Some of these behaviours can be done with commands but how to solve dynamic enabled/disable in datagrid/tree, where permission changes based on underlaying data? My idea was to introduce simple wrapper class
Enableable(of T) implementing INotifyPropertyChanged with just two properties:
Property Value
Property IsEnabled

and every Property in ViewModel should be Type of Enableable(of T)
like

but I can't bind to generic type Enableable(of T). I don't see how to connect this together. If this is impossible to do my concept is for nothing - otherwise you have to make style for every Property

I think this can be very helpful when designing any application which has to test user specific permission - to read permission set based on database/XML/etc and set just property.IsEnabled.

Every Property in ViewModel need default value true/false and if you wish to change it just add row in database with element name.

The "second" part of this idea was to add to main window "rights on load" checker which will change isEnabled/isVisible value of properties defined in table - can be also property in VM binds to Visible/IsEnabled depending on element type

Do you have any hint how to do this? Thank you very much for your advice or just try to push me back to right way

Great article!! I needed to create a treeview that had two different ViewModels--one for the first generation and one for their children. This article was a huge help!!

One slight issue I am having, however, deals with the Search. When I type in a string and step through the code, the application is finding the correct item (whether first generation or child). However, when my search selects a first generation item, it does not appear to be selected visually, even though the IsSelected property is true. Also, when my search selects a child item, the first generation is collapsed visually, even though the first generation item's IsExpanded is set to true. When I manually expand the first generation item, the child is selected. Any idea why the code in the ViewModel and outcome in the View are not in sync?

I know that the IsExpanded and IsSelected properties are using the INotifyPropertyChanged event properly when I am just expanding, collapsing, and selecting items on the treeview without using the search.

I used your sample to create a project with a treeview. The datacontext is an object that is updated by users. When a new item is entered into the datasource, it is not reflected on the tree if the tree is expanded to that level. The LoadChildren function is called correctly if that level has not been expanded on the treeview. I thought that the ObservableCollection would cause the LoadChildren function to run when new items are created. Any help is appreciated greatly!
Thanks,

Dear Hector,
Were you able to find the solution for the above scenario. If not here is what i have done.

If you see data item Children is ObservableCollection and declared as below.
ObservableCollection<TreeViewItemViewModel> Children

And in the example the loding of all children is done only once using LoadChildren() Method. So anytime your model is updated, then this Children collection needs to be updated based on the changes done in your model. The moment you update the Children collection, and since it's ObservableCollection it's make UI to update.

So what i have done is, i have modified the LoadChildren() Method in order to update the changes accordingly.