bacil82
bacil82

Reputation: 11

How to disable expanding/collapsing of tree items in WPF TreeView on double-click

How can I disable tree items collapsing/expanding when I double-click on tree item? I still would like to do this by clicking on toggle button, but not when I double-click on item.

This is XAML I have:

<TreeView Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Categories}" helpers:TreeViewHelper.SelectedItem="{Binding SelectedCategory, Mode=TwoWay}" >
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type core:Category}" ItemsSource="{Binding SubCategories}">
            <Label Content="{Binding Name}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseDoubleClick">
                        <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.CreateGroupsFromCategoryCommand , Mode=OneWay}" CommandParameter="{Binding}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Label>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

I would like to do this only in XAML.

Thank you for your help.

Upvotes: 1

Views: 3584

Answers (4)

RevitArkitek
RevitArkitek

Reputation: 161

I know this issue is old, but I found a slightly different way that preserves the wanted double-click behavior but stops the expand/collapse in case it helps someone.

Keep your typical double click method:

private void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
   // Do something
}

Create an inherited class from TreeView (such as MyTreeView). Add the following to that inherited class:

    protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
    {
        var tvi = GetTreeViewItemFromObject(ItemContainerGenerator, SelectedItem);
        if (tvi != null) tvi.IsExpanded = true;

        base.OnMouseDoubleClick(e);
    }

    /// <summary>
    /// Use the object to get its Tree View item
    /// </summary>
    /// <param name="container"></param>
    /// <param name="targetObject"></param>
    /// <returns></returns>
    private TreeViewItem GetTreeViewItemFromObject(ItemContainerGenerator container, object targetObject)
    {
        if (container.ContainerFromItem(targetObject) is TreeViewItem target) return target;
        for (int i = 0; i < container.Items.Count; i++)
            if ((container.ContainerFromIndex(i) as TreeViewItem)?.ItemContainerGenerator is ItemContainerGenerator childContainer)
                if (GetTreeViewItemFromObject(childContainer, targetObject) is TreeViewItem childTarget) return childTarget;
        return null;
    }

The GetTreeViewItemFromObject method was lifted from someplace else. I don't remember where.

Upvotes: 0

SkyDancer
SkyDancer

Reputation: 159

XAML:

<TreeView x:Name="TreeView1" MouseDoubleClick="TreeView1_MouseDoubleClick" />

C# Code:

private void TreeView1_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    e.Handled = true;
}

Works fine for me.

Upvotes: 0

RonnyR
RonnyR

Reputation: 230

You could implement a custom EventTrigger in your views code behind, as suggested here: https://stackoverflow.com/a/7688249/1206431

public class HandlingEventTrigger : System.Windows.Interactivity.EventTrigger
{
    protected override void OnEvent(System.EventArgs eventArgs)
    {
        var routedEventArgs = eventArgs as RoutedEventArgs;
        if (routedEventArgs != null)
            routedEventArgs.Handled = true;

        base.OnEvent(eventArgs);
    }
}

Add the namespace to your view like this xmlns:views="clr-namespace:YourNamespace.Views"

And then replace <i:EventTrigger EventName="MouseDoubleClick"> with <local:HandlingEventTrigger EventName="PreviewMouseDoubleClick">.

The HandlingEventTrigger will stop the event from being passed further up the visual tree and therefore not expanding/collapsing your tree, and using PreviewMouseDoubleClick instead of MouseDoubleClick will allow you to still fire your own command.

Upvotes: 0

Cinchoo
Cinchoo

Reputation: 6322

You should suppress the double click event on treeviewitem:

<TreeView Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Categories}" helpers:TreeViewHelper.SelectedItem="{Binding SelectedCategory, Mode=TwoWay}" TreeViewItem.PreviewMouseDoubleClick="TreeViewItem_PreviewMouseDoubleClick" >
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type core:Category}" ItemsSource="{Binding SubCategories}">
            <Label Content="{Binding Name}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseDoubleClick">
                        <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.CreateGroupsFromCategoryCommand , Mode=OneWay}" CommandParameter="{Binding}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Label>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Code Behind:

private void TreeViewItem_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    //this will suppress the event that is causing the nodes to expand/contract 
    e.Handled = true;
}

Upvotes: 1

Related Questions