Binding a TreeView to a DataSet

This blog entry demonstrates the fundamentals of binding a WPF TreeView to a DataSet with two related DataTables. The technique presented herein could easily be extended to fit more sophisticated requirements, such as binding to more than two tables.

Many applications need to display hierarchical data in a TreeView, and often that data is retrieved from a database. In many situations the developer just needs to bind the TreeView directly to the DataSet which was populated with database data; creating custom domain objects and collections of those objects can be overkill sometimes. If you are currently in that situation, rest assured that it is actually fairly trivial to do this in WPF. :)

The basic gist of the solution is to bind the top level of TreeViewItems against the master DataTable, and then bind against DataRelations for any descendants of the root nodes. You need to use a HierarchicalDataTemplate for every non-leaf level of nodes, in other words, only the very lowest DataTable in the hierarchy is displayed with a non-hierarchical DataTemplate.

Let’s just get right into an example. Here is a method in a class called DataSetCreator which creates a DataSet with two related DataTables:

Creating a hierarchical DataSet

The resultant DataSet has two DataTables (‘Master’ and ‘Detail’) and one DataRelation (‘Master2Detail’). We want a TreeView to display the Master rows as top-level nodes and the Detail rows as children of their respective parent node. Here is the XAML for a Window which contains a TreeView configured to load and display that data:

Binding a TreeView to a DataSet

If you had, say, three related tables (Master –> Detail –> DetailInfo) then you could have the ‘DetailTemplate’ be a HierarchicalDataTemplate whose ItemsSource was bound to the DataRelation between ‘Detail’ and ‘DetailInfo,’ and the ItemTemplate a DataTemplate which displays the pertinent information in that table.

When you run the demo application and expand the root nodes, the TreeView looks like this:

The bound TreeView

 Click here to download the demo project.  Be sure to change the file extension from DOC to ZIP and then unzip it.

30 Responses to “Binding a TreeView to a DataSet”

  1. Matthieu MEZIL Says:

    It is really easier than with “classic” WinForms !

  2. Josh Smith Says:

    Matthieu,

    It certainly is. The WinForms TreeView does not provide any way to automatically generate its nodes based on a data source. The WPF TreeView makes this very easy. WPF rocks!

    Josh

  3. Joe's Blog : "Adventures in WPF" Presentation Demos and Links Says:

    [...] Josh Smith on WPF - Hierarchal Data Binding [...]

  4. Michael Says:

    I am a complete noob at this so bear with me.

    When I open the Window1.xaml, I get an error:

    Assembly ” was not found. The ‘clr-namespace’ URI refers to an assembly that is not referenced by the project.

    Am I missing something?

  5. Michael Says:

    I had a look through the WPF Forums and consensus was that this is a bug.

  6. Josh Smith Says:

    Michael,

    Visual Studio’s XAML support is not quite “there yet.” It gives warnings for perfectly valid XAML constructs, which you can safely ignore.

    Josh

  7. Govind Says:

    Is there any way to select a treeview node (arbitrary child object) by passing a key, like we used to do in Windows common control library. ?
    When we want to select a Node, we could write this in VB6:

    Set tvw.SelectedItem = tvw.Nodes.Items(”KEY1″ ;)

    “KEY1″ is a unique key for every node, Unique key was assigned while populating the treeview.

    Additionally how to use tvw.Items.Contains method ?
    I think contains method only work at own level (not nested). Because Items collection is a new object for each child treeviewitem, this is very bad and consuming lots of memory, anyways, please help me.
    Thanks.
    Govind

  8. Josh Smith Says:

    Govind,

    No, TreeViewItems in WPF do not have a Key property.

    The Items collection of TreeView only contains the data objects represented by the root-level nodes. You must use a recursive technique to walk through the items and set the IsSelected property to true on the TreeViewItem which you want to select.

    Josh

  9. Govind Says:

    Thanks Josh, But IsSelected is a read-only property, I remebered
    I tried the recursive technique for checking the desired object existance, But I think ICompare interface can help me for nodes comparsion this will also help me in sorting the tree, I will try this.

    Additionally, I saw a method in Items property called MoveToCurrent (not exactly sure the name) as per doc it will select given node or will return false upon failure. But this method is also doesn’t work for me and always returns fails even I passed a true object. I will submit my code tomorrow. Many many thanks for replying.
    Govind

  10. Josh Smith Says:

    Govind,

    You should post further questions/code on the WPF Forum: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&SiteID=1

    Josh

  11. George Says:

    Hi,
    What about the case where you have a single table with a self reference?
    I’ve tried to modify the code but no luck :(

  12. Josh Smith Says:

    George,

    Hmmm, that’s an interesting question. You might want to search the WPF Forum, or post a question about it if you can’t find an answer. I’ve never tried to do that in WPF before.

    Josh

  13. LE Marek Says:

    I used this binding(solution1), works good, but some thing works else then if I fill TreeView by treeview.Items.Add() (solution2).

    For example:
    1) change Foreground of selected node. I get from treeview.SelectedItem
    Sol 2: TreeViewItem
    Sol 1: DataRowView
    > So how can I access to treeviewitem.Foreground, if I get DataRowItem, respectively, how to change color of text of selected node?

    2) using treeview.FindName(registeredName)
    >What is registered name in sol 1? So how can I find node if I know ID of row from table to be able for example change text color?

    Any help welcome.
    Thanks,

    Marek

  14. Abhinav Says:

    Hi,
    i have bound the TreeView to the Dataset and geet the Item. But they not TreeView Item . Neither I can TypeCast them to Treeview. Actually i want to write a Event Handleron the click of the Items. How can I do this?

    Bye

  15. Josh Smith Says:

    For general purpose questions about WPF, you should ask them on the WPF Forum: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&SiteID=1 First search the forum to see if the question has already been answered.

    If you have a question which relates to the topic of a blog post, then leave it as a comment on that post.

    Thanks,
    Josh

  16. Abhinav Says:

    Hi,

    Can we do this when there are more than a DataRelation and I Want multiple levels i.e Nested Nodes.

    Thanks
    Abhinav

  17. Radek Says:

    Hi.

    Help me please. A need more as two tables bind to a treeview. Between tables in dataset I have relations. But this work onlly between two tables.

    Can we write any examle me.

    I have Visual C# 2008 Express.

    Radek

  18. Josh Smith Says:

    Abihav,
    This post mentions that situation, under the xaml snippet.

    Radek,
    I’m not going to write an example for you. If you have a question which needs to be answered with any urgency, don’t post it here. Post it to the WPF Forum: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&SiteID=1

    Josh

  19. Eric Cosky Says:

    Very informative example. Thanks for the write up!

  20. Freddy Op de Beeck Says:

    Hi,

    The code works fine to fill a treeview with a dataset.
    But, since you don’t use a treeview.item, how can you directly expand the whole treeview?

    Freddy.

  21. Data Binding, the WPF way - Noticias externas Says:

    [...] http://joshsmithonwpf.wordpress.com/2007/05/05/binding-a-treeview-to-a-dataset/ [...]

  22. Geert Diddens Says:

    Hi Freddy,

    You should use a style for this (put it in the Xaml file, before the treeview :

    greetz
    Geert D.

  23. Geert Diddens Says:

    Hi Freddy,
    Put this in your XAML file (before the treeview). ( Change the ‘{’ to ”, had do this, because the code wouldn’t post otherwise)

    {ResourceDictionary}
    {Style TargetType=”TreeViewItem”}
    {Setter Property=”IsExpanded” Value=”True”/}
    {/Style}
    {/ResourceDictionary}
    greetz
    Geert

  24. Kieran Says:

    Great TreeView, but is there any way to implement sorting of the tree nodes??
    I have tried sorting the data withjin the dataset but I can’t get the tree view to update - any ideas??

  25. Josh Smith Says:

    Kieran,

    When you bind to a collection, you’re actually binding to an ICollectionView implementation wrapped around the collection. ICollectionView supports sorting.

    Josh

  26. Plastio Says:

    What about one table which is arranged with parentID and ObjectID kind a like internal hirarchy ?
    any ideas how not to break balls around this issue please ?

    ADV thanks ANCE

  27. Azat Says:

    Hi Josh!

    You showed an example with Dataset. What about LINQ to SQL classes? I couldn’t find anything bout that. Can you help me, please? Thanx… ;-)

  28. Chris Koenig : Hierarchical Databinding in WPF Says:

    [...] http://joshsmithonwpf.wordpress.com/2007/05/05/binding-a-treeview-to-a-dataset/ [...]

  29. Hierarchical Databinding in WPF - ChrisKoenig Says:

    [...] http://joshsmithonwpf.wordpress.com/2007/05/05/binding-a-treeview-to-a-dataset/ [...]

  30. Hierarchical Databinding in WPF - MSDN Blogs - Wroc.NET Says:

    [...] http://joshsmithonwpf.wordpress.com/2007/05/05/binding-a-treeview-to-a-dataset/ [...]

Leave a Reply