2017-01-26 3 views
0

Actuellement j'expérimente avec un ControlTemplate qui a un ListBox et un chevauchement Popup qui devrait se déclencher une fois que je passerai la souris sur le ListBox. Maintenant, cela fonctionne bien comme dans les affichages Popup dès que je survole le ListBox.Pourquoi ce déclencheur est-il mis à jour lorsque sa valeur est fausse?

Cependant, dès que je quitte le ListBox comme le vol stationnaire au-dessus de la Popup le déclencheur semble mettre à jour le IsOpen -Property à nouveau et ferme la Popup. D'après ce que j'ai compris, le déclencheur ne devrait se déclencher que lorsque la propriété IsMouseOver -Property est définie sur true et que le Popup doit rester ouvert (ce que j'ai prévu car il doit contenir des éléments cliquables).

Est-ce que j'ai une erreur logique ou comment le déclencheur fonctionne-t-il exactement dans ce cas?

<ControlTemplate x:Key="SelectTargetsListBox"> 
    <Grid> 
     <ListBox x:Name="PART_ListBoxBonusTargets" Height="200" 
       ItemsSource="{Binding Path=Targets}" /> 
     <Popup Name="PART_PopupListBoxBonusTargets" 
       PlacementTarget="{Binding ElementName=PART_ListBoxBonusTargets}" 
       Placement="Right" 
       VerticalOffset="-10" HorizontalOffset="-10" 
       PopupAnimation="Fade" AllowsTransparency="True" StaysOpen="True"> 
      <Border MinHeight="300" MinWidth="400" 
        Background="{StaticResource BonusPopupBackgroundColor}" 
        BorderBrush="{StaticResource BonusForegroundColor}" 
        BorderThickness="3"> 
      </Border> 
     </Popup> 
    </Grid> 
    <ControlTemplate.Triggers> 
     <Trigger SourceName="PART_ListBoxBonusTargets" 
       Property="IsMouseOver" Value="True"> 
      <Setter TargetName="PART_PopupListBoxBonusTargets" 
        Property="IsOpen" Value="True" /> 
     </Trigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 

Répondre

1

Ai-je une erreur logique ou comment exactement le déclencheur fonctionne-t-il dans ce cas?

La propriété IsOpen du menu contextuel ne sera vraie que si la condition de déclenchement est vraie. Lorsque la condition de déclenchement devient fausse, la propriété IsOpen est réinitialisée à sa valeur par défaut false. Pourquoi? Parce que c'est ainsi que fonctionnent les déclencheurs dans WPF. Rappelez-vous que XAML est un langage de balisage et même si vous pouvez réellement implémenter certaines choses en XAML pur, cela ne veut pas dire que vous devriez toujours le faire. Un langage de programmation comme C# est plus concis et expressif que XAML et devrait généralement être utilisé pour implémenter n'importe quel comportement dans votre application.

Ceci est un exemple où il serait beaucoup plus facile de gérer les événements de la souris par programmation et de définir explicitement la propriété IsOpen du Popup sur true/false au lieu d'essayer d'utiliser des déclencheurs XAML.

+0

Y at-il une notion de pourquoi les déclencheurs fonctionnent comme ça? Btw. Je pense que je vais le faire dans le modèle de vue, mais j'étais curieux de savoir si cela pouvait être fait avec des déclencheurs XAML. – Adwaenyth

+0

"Les propriétés modifiées par les déclencheurs sont automatiquement réinitialisées à leur valeur précédente lorsque la condition déclenchée n'est plus satisfaite": https://msdn.microsoft.com/en-us/library/system.windows.trigger(v=vs. 110) .aspx. C'est le comportement attendu. Considérons par exemple que vous appliquez un déclencheur IsMouseOver à un élément. Ensuite, vous ne voudriez pas que cette brosse reste quand la souris part. Ce serait très étrange. – mm8

1

Le déclencheur est déclenché chaque fois IsMouseOver changement de propriété. Si la valeur est true, elle déclenchera les modifications que vous avez définies dans Trigger sinon elle reviendra à l'état initial.

La bonne façon serait de le faire par appel événement, je ne sais pas si le meilleur événement, mais comme vous avez un exemple:

<ListBox MouseEnter="ListBox_MouseEnter" x:Name="PART_ListBoxBonusTargets" Height="200" 
      ItemsSource="{Binding Path=Targets}" /> 

private void ListBox_MouseEnter(object sender, MouseEventArgs e) { 
     e.Handled = true; 
     PART_PopupListBoxBonusTargets.IsOpen = true; 
    } 
+0

Je sais que je peux le faire si je câble l'événement 'MouseEnter'. Si rien d'autre ne m'aide, j'irais même si loin pour faire une propriété dans le viewmodel. Je suis cependant curieux de savoir pourquoi le déclencheur provoquerait un changement à la vue lorsque sa condition n'est pas remplie. Vous avez dit "renvoyer à l'état initial". Pourquoi ça fait ça? – Adwaenyth

+0

Pour clarifier, quel est le raisonnement derrière ce comportement? Est-ce pour éviter que quelqu'un n'oublie de se déclencher sur le «faux» cas ou a-t-il des antécédents plus profonds que je ne connais pas? – Adwaenyth

+1

Un déclencheur est déclenché chaque fois que la propriété liée est "mise à jour". Donc, quand vous quittez ListBox, votre propriété 'IsMouseOver' est mise à jour à false car c'est une propriété de dépendance que votre thread vérifie s'il y a quelque chose à mettre à jour et dans votre cas il va refaire la vérification du' Trigger' que vous définissez – Safe