В WPF как выбрать элемент дерева под моим курсором при щелчке правой кнопкой мыши? - PullRequest
17 голосов
/ 28 апреля 2009

В WPF, когда я щелкаю правой кнопкой мыши по элементу дерева, я хочу, чтобы он был выбран / активирован перед отображением контекстного меню.

Это звучит довольно просто, но включение иерархического DataTemplate немного усложняет.

У меня есть следующее дерево:

<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>

А вот и мой обработчик событий ...

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

}

Обратите внимание, как я добавляю 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>

Есть идеи, почему при щелчке правой кнопкой мыши выбирается только корневой узел вместо дочерних узлов?

Ответы [ 3 ]

15 голосов
/ 28 апреля 2009

Это потому, что ItemContainerStyle не наследуется дочерними узлами. Вам нужно добавить тот же EventSetter для ItemContainerStyle или вашего 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>
5 голосов
/ 15 ноября 2011

просто прокомментируйте e.Handler=true из вашего обработчика событий.

как это:

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

}
0 голосов
/ 16 сентября 2013

У меня была такая же проблема - не удалось получить правильно выбранный элемент дерева. И вместо использования события PreviewMouseRightButtonDown я использовал то же самое событие StackPanel, которое также хранит все необходимые данные:

<StackPanel DataContext="{Binding}" MouseLeftButtonDown="StackPanel_MouseLeftButtonDown">
....
</StackPanel>

И код обработчика событий:

 private void StackPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            StackPanel panel = sender as StackPanel;
            if(panel==null)return;
            MyTreeViewItem myClicked = panel.DataContext as MyTreeViewItem;
            if (myClicked == null) return;
...
}

MyTreeViewItem - мой пользовательский тип данных; myClicked теперь хранит данные, связанные с выбранным элементом дерева. Надеюсь, это поможет кому-то вроде меня.

...