2009-11-05 5 views
14

NOTE J'ai posé la question connexe (avec une réponse acceptée): How to combine DataTrigger and Trigger?Comment combiner DataTrigger et EventTrigger?

Je pense que je dois combiner une EventTrigger et un DataTrigger pour obtenir ce que je suis après:

  • quand un article apparaît dans ma ListBox, il devrait clignoter quelques instants
  • si l'article est 'Critique' alors il devrait rester en surbrillance

Actuellement, j'ai un DataTemplate qui ressemble à ceci:

<DataTemplate DataType="{x:Type Notifications:NotificationViewModel}"> 
    <Grid HorizontalAlignment="Stretch"> 
     <Border Name="Background" CornerRadius="8" Background="#80c0c0c0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
     <Border Name="Highlight" CornerRadius="8" Background="Red"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
     <!-- snip actual visual stuff --> 
     <Grid.Triggers> 
      <EventTrigger RoutedEvent="Grid.Loaded"> 
       <EventTrigger.Actions> 
        <BeginStoryboard> 
         <Storyboard> 
          <DoubleAnimation x:Name="LoadedAnimation" 
              Storyboard.TargetName="Highlight" 
              Storyboard.TargetProperty="Opacity" 
              From="0" To="1" 
              RepeatBehavior="5x" 
              Duration="0:00:0.2" 
              AutoReverse="True" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger.Actions> 
      </EventTrigger> 
     </Grid.Triggers> 
    </Grid> 
    <DataTemplate.Triggers> 
     <DataTrigger Binding="{Binding Path=IsCritical}" Value="True"> 
      <Setter TargetName="LoadedAnimation" Property="RepeatBehavior" Value="5.5x" /> 
     </DataTrigger> 
    </DataTemplate.Triggers> 
</DataTemplate> 

L'idée est qu'un EventTrigger anime l'opacité de la frontière Highlight entre 0 et 1 et à nouveau à plusieurs reprises lorsque l'élément est d'abord chargé, en tirant la l'attention de l'utilisateur. Le DataTrigger détermine le nombre de fois à animer. Si le modèle de vue signale que l'élément IsCritical alors l'animation se produit 5,5 fois (de sorte qu'il se termine à l'opacité 1), sinon il se produit 5 fois (se terminant à l'opacité 0.)

Cependant le XAML ci-dessus ne fonctionne pas parce que le setter de DataTrigger échoue avec:

Enfant avec le nom 'LoadedAnimation' introuvable dans VisualTree.

Assez juste. Donc, loin d'utiliser un convertisseur de valeur personnalisé ou de mettre le nombre d'animation sur le modèle de vue et de le lier, quelles sont mes options?

+0

Il pourrait être utile http://stackoverflow.com/questions/2764415/how-to-give-the-condition-for-eventtrigger –

Répondre

-3

Essayez quelque chose comme ceci:

<Style x:Key="EventTriggerStyleKey"> 
    <Style.Triggers> 
    <EventTrigger RoutedEvent="some event here"> 
     <!-- your animation here --> 
    </EventTrigger> 
    <Style.Triggers> 
</Style> 

<Style x:Key="myStyleKey"> 
    <Style.Triggers> 
    <DataTrigger Binding="....." Value="......"> 
     <Setter Property="........." Value="......."/> 
     <Setter Property="Style" Value="{StaticResource EventTriggerStyleKey}"/> 
    </DataTrigger> 
    <Style.Triggers> 
</Style> 
+4

Avez-vous essayé? C'est mon expérience que vous ne pouvez pas avoir un style qui définit un style. –

+1

Vous ne pouvez pas définir un style dans un style –

0

Si vous avez accès au SDK Blend (vous devriez si vous utilisez VS2012 +), vous devriez être en mesure d'y parvenir entièrement en XAML, avec quelque chose comme ça (Avertissement: non testé):

<Grid HorizontalAlignment="Stretch"> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="NotificationStates"> 
      <VisualState x:Name="Flashing"> 
       <Storyboard> 
        <DoubleAnimation x:Name="LoadedAnimation" 
            Storyboard.TargetName="Highlight" 
            Storyboard.TargetProperty="Opacity" 
            From="0" To="1" 
            RepeatBehavior="5x" 
            Duration="0:00:0.2" 
            AutoReverse="True" /> 
       </Storyboard> 
      </VisualState> 
      <VisualState x:Name="Normal" /> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 
    <Border Name="Background" CornerRadius="8" Background="#80c0c0c0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
    <Border Name="Highlight" CornerRadius="8" Background="Red"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
    <!-- snip actual visual stuff --> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Loaded"> 
      <ic:GoToStateAction StateName="Flashing"/> 
     </i:EventTrigger> 
     <ie:DataTrigger Binding="{Binding Path=IsCritical}" Value="True"> 
      <ic:GoToStateAction StateName="Flashing"/> 
     </ie:DataTrigger> 
    </i:Interaction.Triggers> 
</Grid> 

Extrait scénarimage à un VisualState, puis utilisez la bibliothèque d'expression pour changer d'état dans le XAML. Vous aurez besoin de la bibliothèque Microsoft.Expression.Interactions, voir aussi WPF/Silverlight States - Activate from XAML?

0

J'utiliserais un comportement au lieu de déclencheurs dans ce cas. Vous pouvez écrire un comportement qui attache un gestionnaire d'événements à l'événement de chargement de l'objet associé, puis applique l'animation. Le comportement peut exposer certaines propriétés, j'exposerais une propriété AnimationCount (int) qui indique au comportement combien de temps pour répéter l'animation sur l'élément auquel il est associé. Vous pouvez ensuite lier cette propriété à la propriété iscritical dans le modèle de vue et d'utiliser un convertisseur de valeur pour convertir faux à 5 et fidèle à 5,5

Hope this helps

0

Je sais que vous avez dit que vous n'étiez pas vif sur la idée d'un convertisseur, mais il semble que les solutions Blend nécessitent l'installation d'une bibliothèque.Le convertisseur n'a pas l'intention beaucoup de travail et signale que le taux est directement dépendant de la propriété IsCritical:

public class CriticalAnimationRateConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     // Error handling omitted for brevity. 
     if ((bool)value) 
      return new System.Windows.Media.Animation.RepeatBehavior(5.5); 
     else 
      return new System.Windows.Media.Animation.RepeatBehavior(5.0); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

puis mettez à jour votre animation:

<DoubleAnimation Storyboard.TargetName="Highlight" 
       Storyboard.TargetProperty="Opacity" 
       From="0" 
       To="1" 
       RepeatBehavior="{Binding IsCritical, Converter={StaticResource CriticalAnimationRateConverter}}" 
       Duration="0:00:0.2" 
       AutoReverse="True" /> 

Le DataTrigger peut alors être retiré.