Click here to Skip to main content
Click here to Skip to main content

Programmatic Silverlight Tree View Control Node Expansion using View Model (MVVM)

By , 5 Nov 2010
Rate this:
Please Sign up or sign in to vote.

The Silverlight Tree View Control and View Model (MVVM)

Live example: http://silverlight.adefwebserver.com/ViewModelTreeControl

Also see: Silverlight DataTrigger is the Answer to View Model / MVVM issues

When using the Silverlight Tree View Control, you will discover that it is not easy to expand a Tree Node programmatically without using code behind. This article shows how to do that using a Behavior.

Using The Silverlight Tree View Control

Let's look at the normal operation of the Silverlight Tree View Control using View Model (MVVM):

We start off with a simple Category class...

Click to enlarge image

We bind a collection of Categories to the Tree View Control.

We create an ICommand that will set the IsSelected property of one of the nodes:

public ICommand SetCategoryCommand { get; set; }
public void SetCategory(object param)
{  
    foreach (var Cat in colCategory)
    {
        // Find the Node
        var result = (from objCategory in Cat.AllChildren()
                        where objCategory.CategoryName == "Category Sub1-1"
                        select objCategory).FirstOrDefault();
                        
        if (result != null)
        {
            // Set the IsSelected property so the checkbox
            // will be checked
            result.IsSelected = true;
        }
    }
}

private bool CanSetCategory(object param)
{
    return true;
}

We can then invoke the ICommand with a Button, and the check box on the node is selected.

The problem is, if the Silverlight Tree View Control is collapsed, the Node will be checked but you will not know it unless you expand the Tree Node.

Programmatically Selecting The Tree Node

The first step to programmatically selecting the Tree Node is to create a property in the View Model to hold the value of the selected node:

private Category _SelectedCategory;
public Category SelectedCategory
{
    get { return _SelectedCategory; }
    set
    {
        if (SelectedCategory == value)
        {
            return;
        }
        _SelectedCategory = value;
        this.NotifyPropertyChanged("SelectedCategory");
    }
}

And setting the value:

// Set the SelectedCategory property
// so the Behavior will know what node to open
SelectedCategory = objCategorySub0;

Next, we create a Behavior and drop it on the Tree View Control.

We set the Button to trigger the Behavior, and we bind the SelectedCategory to the Behavior.

Notice, there is also a ExpandOnLoad check box, to allow us to indicate if the node should expand when the page is loaded, or when triggered by an event such as a Button click.

When we run the project and click the Button...

The Silverlight Tree View Control Node is automatically expanded.

The Behavior

The Behavior does not consist of a lot of code. This is the method that does most of the work:

private void SelectNode()
{
    // Only try to expand Node if the SelectedCategory is set
    if (SelectedCategory != null)
    {
        // Refresh Tree Control
        objTreeView.UpdateLayout();
        // Get the DataContext of the Tree Control
        MainPageViewModel objMainPageViewModel = 
		(MainPageViewModel)objTreeView.DataContext;
        // Get collection of items bound to Tree Control
        ObservableCollection<category> colCategories = 
		(ObservableCollection<category>)objMainPageViewModel.colCategory;
        
        // Loop through the top levels items
        foreach (var Cat in colCategories)
        {
            // Find the Node - Is it a child of this parent?
            var result = (from objCategory in Cat.AllChildren()
                            where objCategory == SelectedCategory
                            select objCategory).FirstOrDefault();
                            
            // If the selected item is a child of the Parent
            if (result != null)
            {
                // Get the Tree Control node container for the item
                TreeViewItem objTreeViewItem = 
		(TreeViewItem)objTreeView.ItemContainerGenerator.ContainerFromItem(Cat);
                // Expand the Node
                objTreeViewItem.IsExpanded = true;
                
                // Refresh Tree Control
                objTreeView.UpdateLayout();
                
                ExpandChildNode(objTreeViewItem, Cat);
            }
        }
    }
}

// This method expands child nodes
private void ExpandChildNode(TreeViewItem objTreeViewItem, Category Cat)
{
    // Loop through all the sub Categories
    foreach (var item in Cat.Categories)
    {
        // Find the Node - Is it a child of this parent?
        var result = (from objCategory in item.AllChildren()
                        where objCategory == SelectedCategory
                        select objCategory).FirstOrDefault();
                        
        // If the selected item is a child of the Parent
        if (result != null)
        {
            // Get the Tree Control node container for the item
            TreeViewItem SubTreeViewItem = (TreeViewItem)
		objTreeViewItem.ItemContainerGenerator.ContainerFromItem(item);
            // Expand the Node
            SubTreeViewItem.IsExpanded = true;
            
            // Refresh Tree Control
            objTreeView.UpdateLayout();
            
            // Recursively call the function                
            ExpandChildNode(SubTreeViewItem, item);
        }
    }
}

What's Wrong With Code Behind?

There are a number of projects that I am working on where we allow a Designer, with no programming ability, to use Microsoft Expression Blend, to create a UI for a Silverlight Application. For this reason, we do not want to use any code behind, because the Designer would need to know how to program to avoid breaking something.

When we are able to implement Silverlight project with no code behind, we do not have this problem.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

defwebserver
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft MVP. He is a ASP.NET and C# programmer.
 
He is the founder of http://LightSwitchHelpWebsite.com
 
He has a son, Zachary and resides in Los Angeles with his wife Valerie.
Follow on   Twitter

Comments and Discussions

 
QuestionError 2 The type or namespace name 'TargetedTriggerAction' could not be found Pinmemberjohn_172623-Mar-12 8:09 
AnswerRe: Error 2 The type or namespace name 'TargetedTriggerAction' could not be found Pinmemberjohn_172623-Mar-12 8:10 
GeneralRe: Error 2 The type or namespace name 'TargetedTriggerAction' could not be found Pinmemberdefwebserver23-Mar-12 8:29 
GeneralMy vote of 4 PinmemberAlbert van Peppen4-Mar-12 22:33 
Questionhow i expend the tree onload event Pinmemberetty cohen5-Sep-11 20:08 
hi!
 
i try to expand the tree on the onload event and i dont succseded,
 
i add the flowing code:
 
public MainPageViewModel()
       {
           GetCategoriesCommand = new DelegateCommand(GetCategories, CanGetCategories);
           ClearCategoriesCommand = new DelegateCommand(ClearCategories, CanClearCategories);
           SetCategoryCommand = new DelegateCommand(SetCategory, CanSetCategory);
 

           // Load the Categories
           GetCategories(null);
          
         // expand the Categories
          <big> SetCategory(colCategory);</big>       }

and when i run the ptoject i get an error on this row:
 
TreeViewItem objTreeViewItem = (TreeViewItem)objTreeView.ItemContainerGenerator.ContainerFromItem(Cat);
 
because objTreeViewItem is null;
 
can you help me?
 
thank you so mach!!!!
Questionexpanding using code behind PinmemberMember 804595015-Aug-11 3:45 
AnswerRe: expanding using code behind Pinmvpdefwebserver15-Aug-11 4:03 
GeneralMy vote of 5 PinmemberMember 40413413-Mar-11 22:26 
GeneralRe: My vote of 5 Pinmvpdefwebserver15-Aug-11 11:28 
GeneralMy vote of 5 PinmemberKatka Vaughan9-Nov-10 22:54 
GeneralRe: My vote of 5 Pinmemberdefwebserver15-Nov-10 4:05 
GeneralMy vote of 5 Pinmembermamta_m_d9-Nov-10 0:32 
GeneralRe: My vote of 5 Pinmemberdefwebserver15-Nov-10 4:05 
GeneralGreat job Michael PinmvpPete O'Hanlon28-Oct-10 12:27 
GeneralRe: Great job Michael Pinmemberdefwebserver28-Oct-10 12:29 
GeneralRe: Great job Michael Pinmembershakil03040037-Nov-10 3:22 
GeneralRe: Great job Michael Pinmemberdefwebserver7-Nov-10 3:50 
GeneralMy vote of 5 Pinmemberlinuxjr28-Oct-10 2:30 
GeneralRe: My vote of 5 Pinmemberdefwebserver30-Oct-10 7:39 
GeneralColor Scheme, etc. PinmemberDewey22-Oct-10 13:18 
GeneralRe: Color Scheme, etc. Pinmemberdefwebserver22-Oct-10 13:46 
GeneralNice, you may also want to check Joshs master piece out too [modified] PinmvpSacha Barber22-Oct-10 2:23 
GeneralRe: Nice, you may also want to check Joshs master piece out too Pinmemberdefwebserver22-Oct-10 2:45 
GeneralRe: Nice, you may also want to check Joshs master piece out too PinmvpSacha Barber22-Oct-10 5:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140415.2 | Last Updated 5 Nov 2010
Article Copyright 2010 by defwebserver
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid