(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Using the TreeView control in Silverlight

(18 votes)
Martin Mihaylov
>
Martin Mihaylov
Joined Oct 29, 2007
Articles:   50
Comments:   70
More Articles
23 comments   /   posted on Nov 19, 2008
Categories:   Controls
Tweet This!

This article is compatible with the latest version of Silverlight.

Since the first release of Silverlight 2 there was a lot of talk about controls such as TreeView, auto complete TextBox, WrapPanel, DockPanel etc, and because of the high demand some custom controls were created. The Silverlight Toolkit introduced the so long awaited controls. In this article we'll take a closer look at one of them - the TreeView.

Introduction

I believe that most of you are already familiar with the controls of this type either from their web or desktop experience with technologies such as WPF, WinForms or ASP.NET. But for those who are going to be introduced to this type of controls I'll give a short description: The TreeView is a control with tree structure which main purpose is to display hierarchical data in the form of nodes. Each node that has children can be collapsed and expanded.

Getting Started

To start using the TreeView control we must first download the Silverlight Toolkit and after that add a reference to the Microsoft.Windows.Controls.dll.

treeview-1

Next we declare the Microsoft.Windows.Controls namespace in our XAML and add a TreeView in the UserControl:

<UserControl x:Class="SilverlightTools.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:toolkit="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">
    <Grid x:Name="LayoutRoot">
        <toolkit:TreeView x:Name="MyTreeView"></toolkit:TreeView>
    </Grid>
</UserControl>

If you run the application at this time you won’t see anything, because the TreeView element is nothing, but a container for the items that we want to display in hierarchy.

Adding items to the TreeView control

There are two ways to add items to the TreeView control – to add them as static items defined either in the XAML or in the codebehind or to set the ItemsSource property to a collection and define a template for the items.

Static TreeViewItem controls

To add static items to the TreeView control we use the TreeViewItem control:

XAML

<toolkit:TreeView x:Name="MyTreeView">
    <toolkit:TreeViewItem Header="Announcements"/>
    <toolkit:TreeViewItem Header="Products">
        <toolkit:TreeViewItem Header="Controls"/>
        <toolkit:TreeViewItem Header="Media Players"/>
        <toolkit:TreeViewItem Header="Games"/>
        <toolkit:TreeViewItem Header="Charts"/>
    </toolkit:TreeViewItem>
    <toolkit:TreeViewItem Header="Tools"/>
    <toolkit:TreeViewItem Header="Moonlight"/>
    <toolkit:TreeViewItem Header="Demos"/>
    <toolkit:TreeViewItem Header="Learn">
        <toolkit:TreeViewItem Header="Videos"/>
        <toolkit:TreeViewItem Header="Presentations"/>
        <toolkit:TreeViewItem Header="Tutorials"/>
        <toolkit:TreeViewItem Header="Resources"/>
        <toolkit:TreeViewItem Header="Samples"/>
        <toolkit:TreeViewItem Header="QuickStarts"/>
        <toolkit:TreeViewItem Header="Tips and Tricks"/>
    </toolkit:TreeViewItem>
    <toolkit:TreeViewItem Header="Issues"/>
    <toolkit:TreeViewItem Header="Misc"/>
    <toolkit:TreeViewItem Header="Write and Win Contest"/>
</toolkit:TreeView>

C#

TreeViewItem item1 = new TreeViewItem();
item1.Header = "Products";
item1.Items.Add( new TreeViewItem() { Header = "Controls" } );
item1.Items.Add( new TreeViewItem() { Header = "Media Players" } );
item1.Items.Add( new TreeViewItem() { Header = "Games" } );
item1.Items.Add( new TreeViewItem() { Header = "Charts" } );
MyTreeView.Items.Add( item1 );

Using the ItemsSource property

Another way to populate the TreeView is to bind it to a collection and to do that we must set the ItemsSource property and the ItemTemplate property. Before doing that, let's prepare the collection.

Creating the collection

I create a class called Category:

public class Category
{
    public string Name { get; set; }
    public List<Category> SubCategories { get; set; }
}

The property Name contains the name of the category and the property SubCategories contains its children.

I read the categories form the following XML file using LINQ to XML (more about it here): 

<?xml version="1.0" encoding="utf-8" ?>
<categories>
    <category name="Announcements"></category>
    <category name="Products">
        <category name="Controls"></category>
        <category name="Media Players"></category>
        <category name="Games"></category>
        <category name="Charts"></category>
    </category>
    <category name="Tools"></category>
    <category name="Moonlight"></category>
    <category name="Demos"></category>
    <category name="Learn">
        <category name="Videos"></category>
        <category name="Presentations"></category>
        <category name="Tutorials"></category>
        <category name="Resources"></category>
        <category name="Samples"></category>
        <category name="QuickStarts"></category>
        <category name="Tips and Tricks"></category>
    </category>
    <category name="Issues"></category>
    <category name="Misc"></category>
    <category name="Write and Win contest"></category>
</categories>
private void LoadData()
{
    List<Category> categories = new List<Category>();
    XDocument categoriesXML = XDocument.Load( "Categories.xml" );
 
    categories = this.GetCategories( categoriesXML.Element( "categories" ) );
}
 
private List<Category> GetCategories( XElement element )
{
    return ( from category in element.Elements( "category" )
             select new Category()
             {
                 Name = category.Attribute( "name" ).Value,
                 SubCategories = this.GetCategories( category )
             } ).ToList();
}

I use recursion in order to create the hierarchical structure of the categories in the list and to prepare it for use, and now when it's ready let's prepare the TreeView control to accept it.

Setting the Source and defining the templates

When we have a source that our control will bind to, we must also have an item template: 

<toolkit:TreeView x:Name="MyTreeView" BorderThickness="0,0,0,0">
    <toolkit:TreeView.ItemTemplate>
    </toolkit:TreeView.ItemTemplate>
</toolkit:TreeView>

But in our case defining some controls in the ItemTemplate and binding their properties to the objects' properties in the collection is not enough. In the Item template we need to define the hierarchical structure of the collection. For that purpose we use the HierarchicalDataTemplate:

<toolkit:TreeView x:Name="MyTreeView" BorderThickness="0,0,0,0">
    <toolkit:TreeView.ItemTemplate>
        <toolkit:HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
            <StackPanel >
                <TextBlock Text="{Binding Name}"></TextBlock>
            </StackPanel>
        </toolkit:HierarchicalDataTemplate>
    </toolkit:TreeView.ItemTemplate>
</toolkit:TreeView>

All we have to do is to set the ItemSource of the HierarchicalDataTemplate to the child collection of our objects and define the template for the item in it. Everything else will be handled by it. And now we can set the ItemsSource of the TreeView, build and run the application in order to see our category tree.

private void LoadData()
{
    List<Category> categories = new List<Category>();
    XDocument categoriesXML = XDocument.Load( "Categories.xml" );
 
    categories = this.GetCategories( categoriesXML.Element( "categories" ) );
 
    this.MyTreeView.ItemsSource = categories;
}

Styling the TreeView

In this section I'll give you some tips about the advanced styling of the TreeView control using the Expression Blend 2.

While styling it, I have defined the items as static TreeViewControls in the XAML, in order to see something in the Expression Blend Designer. Now let's see what we need in order to style our TreeView.

The thing we'd want to change most probably is the look of the TreeViewItem, so let’s edit a copy of its template:

treeview-2

And here is how the template sub-elements look like:

treeview-3

Now you have the possibility to customize the states of the TreeViewItem (Normal, Disabled, Selected, Unselected) changing the properties of the inactive and select rectangles or recording a new animation for the state. Another thing you can do is to go deeper into the template and modify the ExpanderButton and the Header. You'd probably want to customize the expander according to the design of your application. In the Header you can find the MouseOver state for the TreeViewItem, so it also worths templating.

Here is a little example for what can be done using the Blend to style the TreeView control; I have recreated the Browse menu of SilverlightShow in Silverlight: 

And here is the source code Source code.

Conclusion

Finally we have a basic TreeView control in Silverlight as a part of the Silverlight Toolkit. As we know the demand for such a control was really big, that is why some great proprietary controls were created providing really tremendous functionality (like RadTreeView from Telerik, TreeView for SIlverlight from ComponentOne and etc.). Unlike these controls, the standard tree view isn't so powerful, but I think it has its place in our Silverlight development and I will surely find use of it.


Subscribe

Comments

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Murtaza Ali on Nov 19, 2008 07:01

    This is Quite Good sample

    but what i am intrested is how to show a particular category in the TreeView as Selected

    i am also using the same (treeview with databinding and hirarcheical Template) but i need to show the first item in the treeview as selected

  • Enrai

    RE: Using the TreeView control in Silverlight 2


    posted by Enrai on Nov 19, 2008 08:15

    Hm, for the moment I also haven't found a way to do that, but here are my thoughts about this topic. When using databinding the Items collection of the TreeView contains the collection that I am setting as ItemsSource and there is no sign of TreeViewItem controls. On the other hand when using TreeViewItem controls the Items collection is filled with the defined controls and I can access each item in the collection and its properties. This gives me some freedom to experiment with the items and find a solution for the problem, but there are some issues that I haven't solved so far. For example this:

    public Page()
    {
        InitializeComponent();
        this.MyTreeView.Focus();
        ( ( TreeViewItem )this.MyTreeView.Items[ 1 ] ).IsSelected = true;
        ( ( TreeViewItem )this.MyTreeView.Items[ 1 ] ).Focus();            
    }

    I set the IsSelected proeprty of the desired item to true. When I run the application and the TreeView appears the item is selected but it's in inactive state. If you click on another item it doesn't get unselected. I've tried to focus the TreeView control and its child but it doesn't seem to work, none of them gets focused.

    Another strange thing is that when I select an item and click somewhere on the TreeView outside of the items, the first item gets selected.

    If someone have any ideas, I'll be glad to share them with me. I will continue to dig in the control, so expect more articles about it.

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by austin avrashow on Dec 01, 2008 16:19

    When you set the ItemsSource property to a collection, you defined a class with 2 levels of hierarchy.

    What if I wanted to bind to an XML document that has an unknown number of levels?

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by austin avrashow on Dec 01, 2008 18:14

    I should have asked 'Can you set the ItemsSource property for the TreeView to an XDocument or XElement?'

    [The reason my previous question duplicated was i submitted it, then pressed F5]

  • Enrai

    RE: Using the TreeView control in Silverlight 2


    posted by Enrai on Dec 02, 2008 08:22

    @Austin The Category class allows me to handle unlimited levels of hierarchy, because every sub category has a collection of categories and so on and on. On the other side using the recursion with LINQ to XML there is no problem to read a XML with uknown number of levels. If you want try to add additional levels to the XML file in the source code of the example and you'll see that they are handled properly.

    About your second question: If you set the ItemsSource to an XElement or XDocument (they need a cast) you will have problems defining the bindings in the XAML. For the HierarchicalDataTemplate's source you have to set the Elements("category") collection and then you have to bind the value of the TextBox to the Attribute("Name") value. The binding syntax doesn't support brackets, so it can't be done that way. Probably workarounds can be found, but I don't think there is a need. You can just create a collection, fill it with the needed information from the XML and then define the bindings in the XAML - much easier and the code stays clear and understandable. :)

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Daniel Lyle on Dec 12, 2008 10:17

    Great tutorial.  I like the list of lists approach you suggest and the HierarchialDataTemplate.  The list of lists approach shares in the simple beauty of Lisp style lists.  The HierarchialDataTemplate reminds one of the simple beauty of the Tree controls that Java led the industry with some years ago that truly separated the model from the view.

    I did have a question -- is there a way to create a more generic list than your example recursive Category class?  I guess one could replace the Name string with an Object class (like a void pointer in C).

  • -_-

    Drag and drop in Treeviews


    posted by AbhishekVas on Dec 16, 2008 06:45

    Dear Martin,

    I am interested to know whether we can drag and drop nodes from one tree view to another.

    My problem is that I have two  tree node which are bound to two different XML.

    now if I drag and drop item from one tree node to another, I should be able to do that with corresponding changes in XMLs.

    Regards

    Abhishek Vashistha

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Zain Shaikh on Dec 19, 2008 07:11

    i applied style on the treeview but can you please tell me how to animate on collapsing and expanding...?

  • Enrai

    RE: Using the TreeView control in Silverlight 2


    posted by Enrai on Dec 20, 2008 09:20

    @Daniel Lyle You can design the business object however you like, as long as it provides you with a way to bind the TreeView to it. Instead of using an object class for the Name property you can do the following:

    public class Category<T>
    {
        public T Name{ get; set; }
        ...
    }

    This way you can template the class and pass the type of the property through the class name.

    @ AbhishekVas By default there is no drag and drop functionality in the TreeView control, but there should be no problem to implement such. The RadTreeView by Telerik for example allows dragging and dropping in the tree. Whne you implement the drag and drop functionality you should be able to raise an event when something is dropped. This event can be used to write the new data to the XML file. Good luck!

    @Zain Shaikh To animate the expanding  and collapsing of the nodes you should add a storyboard in the ViewStates for "Expanded" and "Collapsed" of the TreeViewItem, that will animate the container for the sub nodes. For example the Opacity of the "ItemsHost" ItemsPresenter can be easily animated, so the sub nodes will fade in and fade out.

  • -_-

    Change direction of trreview


    posted by hany on Jan 22, 2009 04:31

    how can i change direction of treeview control to "rtl" and writing arabic language element???

    there any property for that purpose???

    how??

  • Enrai

    RE: Using the TreeView control in Silverlight 2


    posted by Enrai on Jan 27, 2009 07:40

    Hi, hany,

    yes, it's possible to change the direction of the text to "rtl". The easiest way is to do this:

    char[] c = this.TextBlockControl.Text.ToCharArray();
    Array.Reverse( c );
    this.TextBlockControl.Text = new string( c );

    This solution was made by Tamir Khason. Now there is also an additional project in CodePlex that is related to the Silverlight 2.0 support for for Hebrew and Arabic languages, again the mastermind is Tamir. And here is also one post from Tim Heuer about the "rtl" languages, probably it will be helpful too.

    On the other hand if you want to change the whole design of the TreeView to right-to-left, which menas the expand-buttons to go to the right side and the alignment of the items to be right, you have to rearrange the template of the TreeView and the TreeViewItem. I don't know what exactly should be changed but I think it would be something that regards the HorizontalAlignments properties and the columns of a few grids. If you need additional help, don't hesitate to ask! ;)

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Al Pascual on Apr 17, 2009 18:47
    How to rebind the collection when it changes?
  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by umer on May 14, 2009 03:47
    thanks for this.. it really helped !!

    i have made a style for TreeViewItem by defining some static Items.. but now i want to apply that style to Items that are databound.

    i am using the same code as you have given above (using HierarchicalDataTemplate) ... help please


  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by yogesh on Sep 11, 2009 12:34

    hi

    I have change my ItemContainerStyle style of Some Items in treeview on button click. please let me know how to refresh the trview componerts.

    thanks

    yogesh

     

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Manu on Jan 06, 2010 16:07

    Hi,

    Thank you for this tutorial.

    I try to translate this in VB.net, but I have problem.

    Imports System  
    Imports System.Collections.Generic  
    Imports System.Linq  
    Imports System.Net  
    Imports System.Windows  
    Imports System.Windows.Controls  
    Imports System.Windows.Documents  
    Imports System.Windows.Input  
    Imports System.Windows.Media  
    Imports System.Windows.Media.Animation  
    Imports System.Windows.Shapes  
    Imports System.Collections.ObjectModel  
    Imports System.Xml.Linq  
     
     
    Partial Public Class MainPage  
        Inherits UserControl  
     
        Public Sub New()  
            InitializeComponent()  
     
        End Sub 
     
        Private Sub LoadData()  
            Dim categories As New List(Of Category)()  
            Dim categoriesXML As XDocument = XDocument.Load("Chenets.xml")  
            categories = Me.GetCategories(categoriesXML.Element("categories"))  
     
        End Sub 
     
        Private Function GetCategories(ByVal element As XElement) As List(Of Category)  
     
            Return From category In element.Elements("category"Select New Category(Name = category.Attribute("name").Value, SubCategories = Me.GetCategories(category))  
     
     
     
        End Function 
    End Class 
     
    Public Class Category  
        Private _Name As String 
        Public Property Name() As String 
            Get 
                Return _Name  
            End Get 
            Set(ByVal value As String)  
                _Name = value  
            End Set 
        End Property 
        Private _SubCategories As List(Of Category)  
        Public Property SubCategories() As List(Of Category)  
            Get 
                Return _SubCategories  
            End Get 
            Set(ByVal value As List(Of Category))  
                _SubCategories = value  
            End Set 
        End Property 
    End Class 

     

    One Error :

    Subcategories is on erreur (Erreur 1 Le nom 'SubCategories' n'est pas déclaré ou ne se trouve pas dans la portée )

     

    Anyome, can I Help Me?

    Thank You

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Jerry on Apr 24, 2010 14:21

    Excellent work....Straight to the point. I could style and populate the treeview in our application in minutes.

    Thanks.

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Brandon on Jun 04, 2010 07:32
    This is a great Tutorial, but when if I go back to my collection and I update an element, the change is not reflected in the treeview but I can definitely see it my collection at runtime.
  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by sudha on Jun 06, 2010 11:32

    Hi,

    this is greate article,

    I am looking for similar requirement,along with have additional requirement.

    I have xml file as

    <?xml version="1.0" encoding="us-ascii"?>
    <navtree type="Offerings Portfolio Map">
     <parent Name="Main Map" >
      <child Name="Security" >
       <child1 Name="Security Advisory Services" >
        <child2 Name="Risk Advisory Services" />
        <child2 Name="Compliance Services" />
        
       </child1>
       <child1 Name="IT Security Design and Implementation">
        <child2 Name="Infrastructure Architecture and Engineering"  />
        <child2 Name="Data Protection Services" >
         <child3 Name="Data Protection for Backup Service" />
         </child2>
        <child2 Name="Managed Messaging and Collaboration" />
        <child2 Name="Fraud Detection and Anti-Money Laundering" />
        </child1>   
      </child>
      <child Name="End User Outsourcing and Support Services" >
       <child1 Name="End User Support Solutions" >
        <child2 Name="End-User Productivity Services (EUPS)" />
        <child2 Name="Desktop Lifecycle Management" />
        
       </child1>
          
       <child1 Name="Platform as a Service Solutions" >
        <child2 Name="Email Management"  />       
       </child1>
       
      </child>
        
     </parent>
    </navtree>

    As soon as i load the page..parent node should be expanded..

    kindly help me how can i achive this.

     

    thanks,

    Sudha

     

     

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Yesubabu on Jun 07, 2010 16:59

    Excellent work.This helped me to start with XML binding in treeview.

    I have a requirement like, instead of simple showing the treeview like:

    > Announcements

    > Products

         > Controls

    > Tools

    I wanted to show the XML nodes as it is. I mean my tree view should output like below:

     <?xml version="1.0" encoding="utf-8" ?>
    <categories>
      <category name="Announcements" ></category>

      <category name="Products">

        <category name="Controls"></category>

      </category>

    </categories>

     Please help me in this.

  • -_-

    RE: Using the TreeView control in Silverlight 2


    posted by Satish Chaudhary on Jun 20, 2010 16:26
    Great Tutorial....Thnx a lot....

    I have a situation wherein items should be dropped only on the nodes....Not above or below the nodes....when I drop an item on the node, its child should be created....

    what should I do for that?

    Thnx in advance....

    Satish Chaudhary
  • lnikolov

    RE: Using the TreeView control in Silverlight


    posted by lnikolov on Dec 22, 2010 18:26
    The article has been updated to the latest version of Silverlight and Visual Studio.
  • AjaySingh

    Re: Using the TreeView control in Silverlight


    posted by AjaySingh on Jul 12, 2012 15:37
    Thank you so much...............
  • yashika.rawat

    Re: Using the TreeView control in Silverlight


    posted by yashika.rawat on Mar 04, 2013 12:32
    Hi, when i try this with less list items( say 5 or 10) it works perfectly fine. but on trying with more than 3000 items, the page is not responding.. may be because it is binding data to treeview at once... please help :(

Add Comment

Login to comment:
  *      *