En WPF, comment puis-je sélectionner l'élément TreeView sous mon curseur sur le bouton droit sur?
-
18-09-2019 - |
Question
Dans WPF, quand je clic droit sur un élément de TreeView Je voudrais qu'il soit sélectionné / Activé avant d'afficher le menu contextuel.
Cela semble assez simple, mais l'inclusion d'un hierachicalDataTemplate complique les choses un peu.
Je le treeview suivant:
<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>
Et voici mon gestionnaire d'événements ...
private void trv_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem item = sender as TreeViewItem;
if (item != null)
{
item.Focus();
e.Handled = true;
}
}
Notez comment ajouter un EventSetter ci-dessus. Cela fonctionne PRESQUE. Mais il ne sélectionne que le nœud TreeView niveau racine (à savoir le parent racine du nœud sur lequel je clique à droite). Cela peut être à cause de mon modèle de données hiérarchique? Ce modèle peut contenir des enfants DU MEME TYPE.
Voici mon modèle de données hiérarchique ...
<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>
Toute idée pourquoi seul le nœud racine au lieu de nœuds enfants sont sélectionnés lorsque je clic droit?
La solution
C'est parce que le ItemContainerStyle n'est pas hérité par les nœuds enfants. Vous devez ajouter le même EventSetter sur le ItemContainerStyle o votre 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>
Autres conseils
juste commenter le e.Handler=true
de votre gestionnaire d'événements.
comme ceci:
private void trv_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem item = sender as TreeViewItem;
if (item != null)
{
item.Focus();
// e.Handled = true;
}
}
J'ai eu le même problème - n'a pas pu obtenir le bon élément de l'arbre sélectionné. Et au lieu d'utiliser événement PreviewMouseRightButtonDown
je même événement d'un StackPanel
qui stocke également toutes les données nécessaire:
<StackPanel DataContext="{Binding}" MouseLeftButtonDown="StackPanel_MouseLeftButtonDown">
....
</StackPanel>
Et le gestionnaire d'événements code-behind:
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
est mon type personnalisé pour les données; myClicked
stocke désormais les données associées à l'élément de l'arborescence cliquée.
Je espère que ça va aider quelqu'un comme moi.