I have a TabControl
with a Border
element that I need to animate (make the border flash Yellow to orange) when a property on a viewmodel is greater than zero, via Data Binding, but remain black if the value is zero. Each TabItem
has it’s own instance of the viewmodel, so the property value could be different for each TabItem
, therefore the animation should only be activated on the appropriate TabItem
.
I have several similar elements, so I am using a MultiDataTrigger
to check for a tag
on the element, as well as check the property value (via a converter).
I can successfully animate the BorderBrush
when selecting a TabItem
where the property value is greater than zero, but when I then select a TabItem
where the property value is equal to zero, the animation should stop, but does not. I am also changing the BorderThickness
and the Margin
, and these settings return to the normal settings as expected, but the animation does not stop.
I am using a Style.Trigger
to apply the animation, and a converter to convert the property’s value from an int
to a boolean
(true if greater than zero, and false if zero).
Here is my xaml code (from app.xaml):
<Style TargetType="{x:Type Border}" x:Key="JobFilterExternalBorder">
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="CornerRadius" Value="3"/>
<Setter Property="Margin" Value="2,0,1,0.8"/>
<Style.Triggers>
<!-- Add Data Trigger to identify if filter is UnprocessedParts and value is > 0, and animate border to imitate a flashing border -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" Value="IsUnprocessed"/>
<Condition Binding="{Binding UnprocessedQty, Converter={StaticResource ConvertNonZeroToBoolean}}" Value="true"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="BorderThickness" Value="6"/>
<Setter Property="Margin" Value="0,-2,-1,-1.2"/>
</MultiDataTrigger.Setters>
<MultiDataTrigger.EnterActions>
<BeginStoryboard Name="FlashStoryboard" Storyboard="{StaticResource AnimationFlashYellowToOrange}">
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="FlashStoryBoard" />
<RemoveStoryboard BeginStoryboardName="FlashStoryBoard"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
And my Storyboard
:
<Storyboard x:Key="AnimationFlashYellowToOrange" Storyboard.TargetProperty="BorderBrush" RepeatBehavior="Forever" Duration="0:0:1" FillBehavior="Stop">
<ObjectAnimationUsingKeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Yellow" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Orange" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
And the view to which this is being applied:
<Border Name="UnprocessedQtyBorder" Tag="IsUnprocessed" Style="{StaticResource JobFilterExternalBorder}" >
</Border>
I can confirm that the MultiDataTrigger
is working fine because the BorderThickness
and changes back to the normal thickness when the MultiDataTrigger
becomes false when selecting a TabItem
where the property value is equal to zero. It’s just the animation that does not stop.
I have tried:
- Adding
StopStoryboard
to theMultiDataTrigger.ExitActions
- Adding
RemoveStoryboard
to theMultiDataTrigger.ExitActions
- Including
FillBehaviour="Stop"
- Adding a second
MultiDataTrigger
to start a new Storyboard that sets theBorderBrush
to black - Changing the order of the
Style
settings to have theMultiDataTrigger
before the standard property settings - Searching the internet for any other examples that might point me in the right direction
I need to have the Storyboard animate the border continuously while the offending element is on screen, so I have included the RepeatBehavior="Forever"
property
I am following MVVM design pattern and would prefer to avoid having code-behind, but I’m not zealous about it.
I have been struggling with this all day and have not made any progress, so this is my last hope.
EDIT:
I suspect the MultiDataTrigger.ExitActions
are never executed in order to stop the Storyboard
, so an additional question must be asked; Is it even possible to stop a Storyboard in this manner? Can the MultiDataTrigger.ExitActions
be triggered to execute some other way?