This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Data Display Controls - TreeView - Basics

The one hundred and seventh part of the Windows Presentation Foundation Fundamentals tutorial begins to examine the TreeView control. This control is used to display hierarchical data.

Routing the Events

You might have expected the two events to be present for the TreeView, rather than its children. However, because of the way that routed events work within WPF, this is not necessary. We can actually capture the events raised by TreeViewItem against the TreeView.

The two events both use the "bubbling" routing strategy. This means that they are initially raised by the TreeViewItem that changed. They are then passed up to their parent control, its parent control and so on.

We can see the bubbling feature immediately by running the program again. Once started, select any child of the Admin item and add a new child to it, using the text box and the button. If you expand or collapse the child of the Admin node, the message box is shown, despite the event being captured at a higher level.

Let's use the bubbling of the routed events to capture them at the TreeView level, whilst removing the event capture from the Admin node. Registering the event is almost identical. The only difference is that you must qualify the event name with the name of the type of control that will raise it.

Update the XAML for the entire TreeView, as follows. Note that we have removed the events from the Admin item and added them to the TreeView directly. They appear as "TreeViewItem.Expanded" and "TreeViewItem.Collapsed" to indicate the type of the event's source control.

<TreeView Name="Tree" Grid.ColumnSpan="2" Margin="0 0 0 2"
    <TreeViewItem Header="Admin">
        <TreeViewItem Header="Rita"/>
        <TreeViewItem Header="Sue"/>
        <TreeViewItem Header="Bob"/>

    <TreeViewItem Header="IT">
        <TreeViewItem Header="Infrastructure">
            <TreeViewItem Header="Tim"/>
            <TreeViewItem Header="Ben"/>
        <TreeViewItem Header="Software Development">
            <TreeViewItem Header="Mel"/>
            <TreeViewItem Header="Jim"/>

    <TreeViewItem Header="Sales">
        <TreeViewItem Header="Dan"/>
        <TreeViewItem Header="Andy"/>

    <TreeViewItem Header="Warehouse">
        <TreeViewItem Header="Cat"/>
        <TreeViewItem Header="Phil"/>

At the moment, the code for the events uses the sender object to determine the item that was expanded. Now that we have registered the events against the TreeView, this will no longer work. We need to obtain the original source of the event instead. This can be found in the OriginalSource property of the event arguments. The property returns an object that must be cast to the expected type.

Modify the code for the two events to use the OriginalSource value:

private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
    var expanded = e.OriginalSource as TreeViewItem;
    var message = string.Format("Expanded to show {0} items", expanded.Items.Count);

private void TreeViewItem_Collapsed(object sender, RoutedEventArgs e)
    var collapsed = e.OriginalSource as TreeViewItem;
    var message = string.Format("Collapsed to hide {0} items", collapsed.Items.Count);

Run the program for a final time to see the results. The message box should now be displayed when any node is expanded or collapsed. It will show the number of items within the manipulated node.

If you select an item by clicking on its text, the ExpandSubtree method will still be used to expand the selected item and all lower nodes in the hierarchy. This will cause multiple message boxes, including ones for the lowest level nodes that contain no children.

27 October 2014