Comment combiner DataTrigger et EventTrigger?
NOTE j'ai posé la question connexe (avec une réponse acceptée): comment combiner DataTrigger et Trigger?
je pense que je dois combiner un EventTrigger
et un DataTrigger
pour réaliser ce que je suis après:
- lorsqu'un élément apparaît dans ma liste, il devrait clignoter pendant quelques instants
- si l'élément est "Critique", alors il devrait rester surligné
actuellement, j'ai un Dataemplate 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 revient à plusieurs reprises lorsque l'article est chargé pour la première fois, attirant l'attention de l'utilisateur. Le DataTrigger
détermine le nombre de fois à animer. Si le modèle de vue indique que l'item IsCritical
alors l'animation se produit 5.5 fois (tel qu'il se termine à l'opacité 1), sinon il se produit 5 fois (se terminant à l'opacité de 0.)
cependant le XAML ci-dessus ne fonctionne pas parce que le setter du DataTrigger ne fonctionne pas avec:
enfant avec le nom "LoadedAnimation" non trouvé dans VisualTree.
très bien. Donc, hésiter à utiliser une valeur personnalisée convertisseur ou de mettre de l'animation compter sur le modèle d'affichage et de liaison, quelles sont mes options?
4 réponses
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 load de l'objet associé et ensuite appliquer l'animation. Le behavior peut exposer certaines propriétés, j'exposerais une propriété AnimationCount (int) qui indique au behavior combien de temps pour répéter l'animation sur l'élément auquel elle est associée. Vous pouvez ensuite lier cette propriété à la propriété IsCritical dans le modèle de vue et utiliser un convertisseur de valeur pour convertissez false à 5 et true à 5.5
Espérons que cette aide
si vous avez accès au Blend SDK (vous devriez Si vous utilisez VS2012+), vous devriez être en mesure de l'accomplir entièrement dans XAML, avec quelque chose comme ceci (disclaimer: untested):
<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>
extraire votre Storyboard à un VisualState, puis utiliser la bibliothèque d'expressions pour changer les états dans le XAML. Vous aurez besoin de Microsoft.Expression.Les Interactions de la bibliothèque, voir aussi WPF/Silverlight États - Activer à partir de XAML?
je sais que vous avez dit que vous n'aimiez pas l'idée d'un convertisseur, mais il semble que les solutions de mélange nécessitent une bibliothèque à installer. Le convertisseur n'est pas beaucoup de travail et signale l'intention que la vitesse dépend directement 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();
}
}
et puis mettre à 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 supprimé.
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>