在WPF中,如何在右键单击光标下选择树视图项?

wil*_*lem 17 wpf treeview treeviewitem

在WPF中,当我右键单击树视图项时,我希望在显示上下文菜单之前选择/激活它.

这听起来很简单,但是包含hierachicalDataTemplate会使事情变得复杂.

我有以下树视图:

<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>
Run Code Online (Sandbox Code Playgroud)

这是我的事件处理程序......

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

}
Run Code Online (Sandbox Code Playgroud)

请注意我如何添加上面的EventSetter.这个ALMOST有效.但它只选择根级树视图节点(即我右键单击的节点的根父节点).这可能是因为我的分层数据模板?此模板可以包含相同类型的子项.

这是我的分层数据模板......

<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>
Run Code Online (Sandbox Code Playgroud)

我右键单击时为什么只选择根节点而不是子节点的任何想法?

Den*_*ler 16

那是因为ItemContainerStyle不是由子节点继承的.您需要在HierarchicalDataTemplate的ItemContainerStyle上添加相同的EventSetter.

<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>
Run Code Online (Sandbox Code Playgroud)

  • 因为您正在处理隧道事件(PreviewXXX事件).这些事件从树的顶部到底部,因此如果您在根处设置e.Handled = true,它将停在那里而不是将树向下隧道到您的项目. (4认同)
  • 我发现使用MouseRightButtonDown(而不是预览版本)更自然.这意味着你_should_使用`e.Handled = true`但是更容易集成_Ctrl_-右键单击逻辑来处理多项选择.(按住Ctrl键右键选择层次结构中的所有节点,因为使用预览事件进行隧道传输而没有"e.Handled".) (2认同)

小智 6

只需e.Handler=true从您的事件处理程序中注释.

像这样:

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

}
Run Code Online (Sandbox Code Playgroud)