Search code examples
wpftreeviewtreeviewitem

In WPF, how do I select the treeview item under my cursor on right-click?


In WPF, when I right-click on a treeview item I would like it to be Selected/Activated before showing the context menu.

This sounds pretty simple, but the inclusion of a hierachicalDataTemplate complicates things a little.

I have the following treeview:

<TreeView 
            x:Name="trv"
            ContextMenu="{StaticResource contextMenu}"
            ItemTemplate="{StaticResource treeHierarchicalDataTemplate}"
            ItemsSource="{Binding Source={StaticResource meetingItems}}" >

            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="trv_PreviewMouseRightButtonDown"/>
                    <Setter Property="IsExpanded" Value="True"></Setter>
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView>

And here is my event handler...

private void trv_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem item = sender as TreeViewItem;
    if (item != null)
    {
        item.Focus();
        e.Handled = true;
    }

}

Note how I add an EventSetter above. This ALMOST works. But it only selects the root-level treeview node (i.e. the root parent of the node on which I right click). This may be because of my hierarchical data template? This template can contain children OF THE SAME TYPE.

Here is my hierarchical data template...

<HierarchicalDataTemplate x:Key="treeHierarchicalDataTemplate" 
                          ItemsSource="{Binding Path=ChildMeetingItems}">
    <HierarchicalDataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=Red}" Value="True">
            <Setter TargetName="img" Property="Image.Source" Value="pack://siteoforigin:,,,/images/bookRed.png"></Setter>
        </DataTrigger>
    </HierarchicalDataTemplate.Triggers>
    <StackPanel 
        x:Name="treeViewItemPanel"
        Background="Transparent"
        Orientation="Horizontal">
        <Image Width="16" Height="16"  x:Name="img" Margin="0,0,4,0" Source="pack://siteoforigin:,,,/images/bookGreen.png"></Image>
        <TextBlock Foreground="DarkGray" Text="{Binding DisplayIndex}" Margin="0,0,5,0"></TextBlock>
        <TextBlock Text="{Binding Summary}"></TextBlock>
    </StackPanel>
</HierarchicalDataTemplate>

Any idea on why only the root node instead of child nodes are selected when I right-click?


Solution

  • That's because the ItemContainerStyle is not inherited by the child nodes. You need to add the same EventSetter on the ItemContainerStyle o your HierarchicalDataTemplate.

    <HierarchicalDataTemplate x:Key="treeHierarchicalDataTemplate" 
                              ItemsSource="{Binding Path=ChildMeetingItems}">
        <HierarchicalDataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=Red}" Value="True">
                <Setter TargetName="img" Property="Image.Source" Value="pack://siteoforigin:,,,/images/bookRed.png"></Setter>
            </DataTrigger>
        </HierarchicalDataTemplate.Triggers>
        <StackPanel 
            x:Name="treeViewItemPanel"
            Background="Transparent"
            Orientation="Horizontal">
            <Image Width="16" Height="16"  x:Name="img" Margin="0,0,4,0" Source="pack://siteoforigin:,,,/images/bookGreen.png"></Image>
            <TextBlock Foreground="DarkGray" Text="{Binding DisplayIndex}" Margin="0,0,5,0"></TextBlock>
            <TextBlock Text="{Binding Summary}"></TextBlock>
        </StackPanel>
    
    <HierarchicalDataTemplate.ItemContainerStyle>
                    <Style TargetType="{x:Type TreeViewItem}">
                        <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="trv_PreviewMouseRightButtonDown"/>                    
                    </Style>
                </HierarchicalDataTemplate.ItemContainerStyle>
    </HierarchicalDataTemplate>