Johan
Johan

Reputation: 31

WPF Storyboard event not firing

I have a simple storyboard that is repeating and auto reversing. When it reaches the end and automatically reverses i would like to fire an event in the code behind. The same for when it repeats. How can i accomplish this? Ultimately i am playing a wav file during these two events. Thanks.

Upvotes: 3

Views: 1382

Answers (1)

Scott
Scott

Reputation: 1876

WPF animations are controlled by an AnimationClock (kinda like a fancy timer). The AnimationClock has a property called CurrentProgress which ranges from 0 to 1; where 0 is the starting point and 1 is the ending point. A repeating storyboard will gradually change the CurrentProgress from 0 to 1 to 0 to 1...

When the AnimationClock instructs the Animation to render its next frame, the Animation raises its CurrentTimeInvalidated event. The sender argument of this event is the AnimationClock. You may inspect the CurrentProgress at this time. However, since this event only triggers when a new frame is drawn the CurrentProgress will probably never be exactly 0 or exactly 1. Instead, you need to look for trends. When you see the trend change, it means the loop has started or has reversed.

Sample xaml:

<Grid x:Name="uxGrid" Background="White">
    <Grid.Triggers>
        <EventTrigger RoutedEvent="Grid.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation Storyboard.TargetName="uxGrid" Changed="ColorAnimation_Changed" CurrentTimeInvalidated="ColorAnimation_CurrentTimeInvalidated"  Storyboard.TargetProperty="Background.Color" From="Blue" To="Green" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Grid.Triggers>
</Grid>

Sample code:

private double? _clockLastProgress;  // Tracks Trend
private bool    _clockLastDecreased; // Tracks Trend Direction

private void ColorAnimation_CurrentTimeInvalidated(object sender, EventArgs e)
{
    AnimationClock clock = sender as AnimationClock;

    if (clock != null && clock.CurrentProgress.HasValue)
    {
        if (!_clockLastProgress.HasValue)
        {
            // Your Code Here
        }
        else
        {
            if (_clockLastDecreased)
            {
                if (clock.CurrentProgress > _clockLastProgress)
                {
                    // Your Code Here
                    _clockLastDecreased = false;
                }
            }
            else
            {
                if (clock.CurrentProgress < _clockLastProgress)
                {
                    // Your Code Here
                    _clockLastDecreased = true;
                }
            }
        }

        _clockLastProgress = clock.CurrentProgress.Value;
    }
}

Upvotes: 3

Related Questions