2010-06-12 10 views
2

Cela fait un certain temps que je rencontre des problèmes et que j'ai trouvé des solutions moins qu'intéressantes. Le problème est que lorsque le menu contextuel d'un TreeViewItem est ouvert, le TreeViewItem est grisé. Est-il possible pour un TreeViewItem de rester en surbrillance pendant que son ContextMenu est ouvert?WPF TreeViewItem Menu contextuel Unhighlights Item

Le problème avec le TreeViewItem gris, c'est qu'il ne donne aucune relation avec le menu contextuel et le TreeViewItem, et il semble moche.

Généralement, le code que j'utilise pour définir un menu contextuel est le suivant. Parfois, le menu contextuel est généré par le code avec un PreviewRightMouseButtonDown EventSetter, mais il ne fait pas de différence:

<TreeView> 
     <TreeView.Resources> 
      <Style TargetType="{x:Type TreeViewItem}"> 
       <Setter Property="ContextMenu"> 
        <Setter.Value> 
         <ContextMenu> 
          <MenuItem Header="Menu Item 1" /> 
          <MenuItem Header="Menu Item 2" /> 
         </ContextMenu> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </TreeView.Resources> 
     <TreeViewItem Header="Item 1"> 
      <TreeViewItem Header="Sub-Item 1"/> 
     </TreeViewItem> 
     <TreeViewItem Header="Item 2"></TreeViewItem> 
    </TreeView> 

Jusqu'à présent, la seule solution que j'ai trouvé est de remplacer le « gris » couleur floue avec le couleur ciblée, mais le TreeView ne semble jamais flou, comme lorsqu'un autre contrôle est cliqué. J'ai aussi eu des problèmes avec ListViews.

Répondre

2

comportement par défaut de WPF est de changer le TreeViewItem gris lorsque le ContextMenu ouvre, mais comme pratiquement tout le reste dans WPF vous pouvez remplacer ceci:

  1. Créer une propriété attachée ContextMenuOpened
  2. Dans le style TreeViewItem, lier ContextMenuOpened à « ContextMenu.IsOpen »
  3. Ajouter un élément déclencheur qui change la brosse lorsque ContextMenuOpened et IsSelected sont vraies

est ici la propriété ci-joint:

public class TreeViewCustomizer : DependencyObject 
{ 
    public static bool GetContextMenuOpened(DependencyObject obj) { return (bool)obj.GetValue(ContextMenuOpenedProperty); } 
    public static void SetContextMenuOpened(DependencyObject obj, bool value) { obj.SetValue(ContextMenuOpenedProperty, value); } 
    public static readonly DependencyProperty ContextMenuOpenedProperty = DependencyProperty.RegisterAttached("ContextMenuOpened", typeof(bool), typeof(TreeViewCustomizer)); 
} 

est ici le compositeur dans le style:

<Setter Property="my:TreeViewCustomizer.ContextMenuOpened" 
     Value="{Binding ContextMenu.IsOpen, RelativeSource={RelativeSource Self}}" /> 

Voici le déclencheur:

<MultiTrigger> 
    <MultiTrigger.Conditions> 
    <Condition Property="IsSelected" Value="true"/> 
    <Condition Property="my:TreeViewCustomizer.ContextMenuOpened" Value="true"/> 
    </MultiTrigger.Conditions> 
    <Setter TargetName="Bd" 
      Property="Background" 
      Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
    <Setter Property="Foreground" 
      Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> 
</MultiTrigger> 

Comment ça marche: Chaque fois que le ContextMenu ouvre sa propriété IsOpen est réglé. La liaison entraîne la définition de votre propriété attachée sur TreeViewItem. Ceci, combiné avec IsSelected, appelle le déclencheur qui modifie les couleurs de premier plan et d'arrière-plan pour que l'élément apparaisse toujours sélectionné.

+0

Génial. Je n'aurais jamais pensé à ça moi-même. Une chose cependant: L'arrière-plan n'est pas défini correctement, mais le premier plan l'est. J'ai le sentiment qu'il a quelque chose à voir avec TargetName = "Bd", qui ne compile pas. – Snea

+0

Ma réponse suppose que votre ControlTemplate TreeViewItem personnalisé est une copie modifiée du ControlTemplate TreeViewItem par défaut. "Bd" est le nom utilisé dans le contrôle TreeViewItem ControlTemplate par défaut pour la bordure. Si vous construisez un ControlTemplate personnalisé pour TreeViewItem au lieu de copier le système et de le modifier, il se peut que vous n'ayez pas de Bordure dans votre modèle ou que ce nom soit différent. Dans ce cas, vous devrez peut-être utiliser un autre TargetName pour définir la couleur d'arrière-plan de l'élément. –

+0

Je viens de me rendre compte que je suppose peut-être trop: Vous n'avez peut-être pas créé de ControlTemplate personnalisé pour TreeViewItem. Dans ce cas, je ne vois aucun moyen d'affecter la couleur de la bordure à l'intérieur du modèle autre que le remplacement des ressources qui, comme vous l'avez noté, a une portée quelque peu globale. Par conséquent, je pense que vous devrez utiliser un ControlTemplate personnalisé. Dans Blend, faites un clic droit sur le contrôle et sélectionnez Modifier le modèle -> Modifier une copie dans le menu contextuel, puis ajoutez mon MultiTrigger au bas de la liste des déclencheurs du modèle. –