Arsen Zahray
Arsen Zahray

Reputation: 25287

How to detect TreeNode expansion in WPF?

I'm using MVVM to bind a hierarchical tree structure to TreeView in WPF. I'm using XAML code, which looks like follows:

<TreeView ScrollViewer.VerticalScrollBarVisibility="Auto"
        BorderThickness="0"
        ItemsSource="{Binding Items}"
        DataContext="{Binding ElementName=UserControl, Mode=OneWay}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:MyStatistics}" ItemsSource="{Binding Items}" >                    
                    <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate> 
...

I want to be able to intercept node expansion event, and let the node of my tree, that is bound to the TreeView node that is being expanded, do some checks, may be ask user if he's sure (if the operation will take a lot of memory) and cancel the expansion.

How do I do that?

Upvotes: 0

Views: 1016

Answers (1)

Dennis
Dennis

Reputation: 20571

This functionality is not built-in and to achieve this you will have to create a new control derived from TreeView and then extend TreeViewItem.

There is fair bit involved to achieve this so I hope you can follow along; I won't explain everything so ask questions or do some reading on MSDN on anything you don't understand.

Creating the TreeView

public class TreeViewEx : TreeView
{

    protected override bool IsItemItsOwnContainerOverride(object item) 
    {
        return (item is TreeViewItemEx);
    }

    protected override DependencyObject GetContainerForItemOverride() 
    {
        return new TreeViewItemEx(this);
    }

    internal bool PreviewExpandTreeViewItem(TreeViewItemEx item)
    {
        // return true to allow expansion, false to cancel
        return true;
    }

}

public class TreeViewItemEx : TreeViewItem
{
    private readonly TreeViewEx Owner;

    static TreeViewItemEx()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeViewItemEx), 
            new FrameworkPropertyMetadata(typeof(TreeViewItemEx)));
    }

    public TreeViewItemEx(TreeViewEx owner)
    {
        Owner = owner;
    }

    private void OnPreviewExpansionMouseDown(object sender, MouseButtonEventArgs e)
    {
        // we do not care if it already expanded
        if (IsExpanded)
            return;

        e.Cancel = !Owner.PreviewExpandTreeViewItem(this);
    }

}

Now, you want to create the default style for your new TreeViewItemEx. You can find the base template on MSDN.

To do this, you will need copy the base template from MSDN, change the TargetType to be {x:Type controls:TreeViewItemEx} and then add a PreviewMouseDown event to the ToggleButton named Expander and use the event handler in the item class e.g. PreviewMouseDown="OnPreviewExpansionMouseDown"

Note: This will only allow you intercept expansion events triggered by the user clicking on the expand button [+]. There are several keyboard shortcuts will you need to implement support for yourself.

HTH,

Upvotes: 1

Related Questions