How to Databind RadTreeView in WPF

Tuesday, August 05, 2008 by Valentin Stoychev | Comments 7

Download the source code of the samples here.

This is the first part of a series of posts demonstrating common scenarios of RadTreeView control. I’ll be covering both WPF and Silverlight. One of the most common scenarios for our customers is populating the RadTreeView with data. In WPF data binding is one of the most powerful concepts. Data binding the Treeview can be done in several ways. In this post I’ll explain the most common scenarios – binding to an XML file, binding to a Collection, and a more advanced sample – data binding using grouping and CollectionViewSource.

XML

  1. Define the XML source
  2. Define the HierarchicalDataTemplates
  3. Set the ItemsSource of RadTreeView

Take a look at the XML data below to see the different XML elements. Basically we have an Artist type which has a collection of Albums; and Album type which has a collection of Songs.

TreeView XML Data binding

First, for defining the XML data we are using the XmlDataProvider. You need to point the Source property to the XML file and set the XPath property to the root element of the XML.

<XmlDataProvider

    x:Key="myArtistsData"

    XPath="/Artists"

    Source="DataSources/Artists.XML"/>

 

Now that we have the data, the next step is to declare the HierarchicalDataTemplates which will “tell” the RadTreeView how to display the XML data.

You need to define HierarchicalDataTemplate for each element type from your XML data. Here is the template for the Artist element:

<!-- DataTemplate for Artist type -->

<HierarchicalDataTemplate

DataType="Artist"

      ItemsSource="{Binding XPath=Albums/Album}">

      <TextBlock FontWeight="Bold" Text="{Binding XPath=@Name}" />

</HierarchicalDataTemplate>

 

It’s all set – now the only thing left is to tell the RadTreeView where the data is – we just need to set the ItemsSource property:

<telerik:RadTreeView

 

            ItemsSource="{Binding Source={StaticResource myArtistsData}, XPath=Artist}"/>

 

That’s it – we are ready. Check the full source code below. 

<Grid> 
    <Grid.Resources> 
          
        <!-- Xml Datasource --> 
        <XmlDataProvider x:Key="myArtistsData" XPath="/Artists" Source="DataSources/Artists.xml"/>  
          
        <!-- DataTemplate for Artist type --> 
        <HierarchicalDataTemplate   
            DataType="Artist"   
            ItemsSource="{Binding XPath=Albums/Album}">  
            <TextBlock FontWeight="Bold" Text="{Binding XPath=@Name}" /> 
        </HierarchicalDataTemplate> 
 
        <!-- DataTemplate for Album type --> 
        <HierarchicalDataTemplate   
            DataType="Album"   
            ItemsSource="{Binding XPath=Songs/Song}">  
            <TextBlock Foreground="Red" Text="{Binding XPath=@Name}" /> 
        </HierarchicalDataTemplate> 
 
        <!-- DataTemplate for Song type --> 
        <DataTemplate   
            DataType="Song">  
            <TextBlock FontStyle="Italic" Text="{Binding XPath=@Name}" /> 
        </DataTemplate> 
    </Grid.Resources> 
 
    <!-- RadTreeView declaration --> 
    <telerik:RadTreeView   
        ItemsSource="{Binding Source={StaticResource myArtistsData}, XPath=Artist}"/>  
</Grid> 

 

Binding to a Collection

This is probably the easiest way to bind the RadTreeView. Here are the steps:

  1. Define the Collection
  2. Set the HierarchicalDataTemplates for each data type
  3. Set the RadTreeView ItemsSource property 

RadTreeView Data binding to a Collection

 

<Grid> 
    <Grid.Resources> 
        <!-- Declare the Collection source --> 
        <sample:LeagueCollection x:Key="MyCollection" /> 
 
        <!-- Declare Templates for each data type --> 
        <DataTemplate x:Key="Team">  
            <TextBlock Text="{Binding Name}"/>  
        </DataTemplate> 
 
        <HierarchicalDataTemplate   
            x:Key="Division"   
            ItemTemplate="{StaticResource Team}"   
            ItemsSource = "{Binding Teams}">  
            <TextBlock Text="{Binding Name}"/>  
        </HierarchicalDataTemplate> 
 
        <HierarchicalDataTemplate   
            x:Key="League"   
            ItemTemplate="{StaticResource Division}"   
            ItemsSource = "{Binding Divisions}">  
            <TextBlock Text="{Binding Name}"/>  
        </HierarchicalDataTemplate> 
    </Grid.Resources> 
      
    <telerik:RadTreeView   
        IsLineEnabled="True" 
        ItemsSource="{Binding Source={StaticResource MyCollection}}" 
        ItemTemplate="{StaticResource League}" /> 
</Grid> 

 

Binding to a CollectionViewSource

(sample is based on Beatriz Costa’s blog)

This is a bit more advanced example. Say you have a flat collection of objects and you want to group it by some common property. For this example we have a collection of animals. Each Animal class has a Category property that we will use in order to create the hierarchical view. The grouping of the data can be easily achieved if we use the WPF CollectionViewSource class.

Here are the steps that we need to follow:

  1. Define the Collection
  2. Configure the CollectionViewSource
    a. Set the Source property to point to our collection
    b. Set the grouping using the GroupDescriptions
  3. Declare the HierarchicalDataTemplate
  4. Set the RadTreeView ItemsSource to point to the CollectionViewSource

RadTreeView Data binbding with CollectionViewSource

 

<Grid> 
    <Grid.Resources> 
        <!-- Declare the source collection --> 
        <sample:Animals x:Key="AnimalCollection"/>  
          
        <!-- Configure the CollectionViewSource --> 
        <CollectionViewSource   
            x:Key="CVS"   
            Source="{Binding Source={StaticResource AnimalCollection}, Path=AnimalList}">  
            <CollectionViewSource.GroupDescriptions> 
                <PropertyGroupDescription PropertyName="Category"/>  
            </CollectionViewSource.GroupDescriptions> 
        </CollectionViewSource> 
 
        <!-- Set the DataTemplate for the Animal --> 
        <DataTemplate x:Key="AnimalTemplate">  
            <TextBlock Text="{Binding Path=Name}"/>  
        </DataTemplate> 
 
        <!-- Set the HierarchicalDataTemplate --> 
        <HierarchicalDataTemplate x:Key="CategoryTemplate" 
                ItemsSource="{Binding Path=Items}"   
                ItemTemplate="{StaticResource AnimalTemplate}">  
            <TextBlock Text="{Binding Path=Name}" FontWeight="Bold"/>  
        </HierarchicalDataTemplate> 
    </Grid.Resources> 
 
    <!-- RadTreeView declaration --> 
    <telerik:RadTreeView   
        IsLineEnabled="True" 
        ItemsSource="{Binding Source={StaticResource CVS}, Path=Groups}"   
        ItemTemplate="{StaticResource CategoryTemplate}"/>  
</Grid> 

 

That's it for now - let me know if you have an interesting scenario that you want to use with RadTreeView - I'll gladly help you!

PS: Our fellows from Silverlightshow.net created a pivot table using our Rad TreeView for Silverlight. Check it out here.

May the source be with you!
 

7 Comments

  • Isaac 10 Aug 2008
    This is great! Could you now show us how to databind wpf treeview to web service? Thanks.
  • Bram 12 Sep 2008
    Nice blog post. I've implemented it in my wpf app but i don't know how to style the color of the nodes (i've changed the datatemplate so it displays an image and so). I've tried setting the foreground but the color of the nodes stay blue green. Any suggestions?
  • Ristogod 08 Oct 2010
    How do you get SelectedItem to work with binding? I've tried and it seems to do nothing?
  • Kiril Stanoev 15 Oct 2010
    @ Isaac
    Please take a look at this help article:
    http://www.telerik.com/help/silverlight/radtreeview-populating-with-data-databinding-to-wcf-service.html

    @Bram
    Could you please post your question and a sample app in our forums or support system. This way we will be better able to assist you.

    @Ristgod
    Basically the idea is the following. Imagine your ViewModel has 2 properties
    - MySelectedItem which is an object
    - MyItems which is a collection of business objects.
    Therefore, after passing the ViewModel as DataContext to the RadTreeView, you can bind both ItemsSource and SelectedItem.

    <telerik:RadTreeView SelectedItem="{Binding MySelectedItem, Mode=TwoWay}" ItemsSource="{Binding MyItems}"/>

    Let me know if this helps. If not, could you please post a more specific questions in our forums or support system.
  • Dave 03 Dec 2010
    How about an example of pulling out data from a database and placing it in a treeview. Then draging the data from onetree view to another then geting the results from the destination tree and writting that back into the database.
  • Allen 15 Jun 2011
    Even better, how about a multi-level grouping example with a CollectionViewSource generated from a flat file format (no embedded lists etc.)
    Thanks.
  • sam 27 Apr 2012
    im crazy ..thats it :O
    how is it binded to ONE Collection ..why not two ?
    one for the parent (node)
    one for the child(node expanded)

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)