R – WPF – Assigning storyboard begintime from parent element

bindingstoryboardwpfxaml

I've got a basic spinner type control I've whipped up, and it works reasonably well, but there's a massive amount of repeated code throughout it. It's essentially the same element over and over again except for two properties, and one of those properties is the BeginTime for the Storyboard – each line just endlessly repeats its animation, but each line starts .1 of a second after the previous one for a nice little wave effect.

Here's the general idea of the code:

<UserControl x:Class="MyNamespace.Spinner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Rectangle Fill="Black" Opacity="0.5"
                   Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=Width}"
                   Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=Height}" />
        <Line X1="9" X2="11" Y1="10" Y2="20">
            <Line.Triggers>
                <EventTrigger RoutedEvent="Line.Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard RepeatBehavior="Forever" Duration="0:0:0.8"
                                        BeginTime="0:0:0.1">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="0%" />
                                    <LinearDoubleKeyFrame Value="1.0" KeyTime="12.5%" />
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="75%" />
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="100%" />
                                </DoubleAnimationUsingKeyFrames>
                             </Storyboard>
                         </BeginStoryboard>
                     </EventTrigger.Actions>
                 </EventTrigger>
             </Line.Triggers>
         </Line>
        <Line X1="14" X2="16" Y1="10" Y2="20">
            <Line.Triggers>
                <EventTrigger RoutedEvent="Line.Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard RepeatBehavior="Forever" Duration="0:0:0.8"
                                        BeginTime="0:0:0.2">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="0%" />
                                    <LinearDoubleKeyFrame Value="1.0" KeyTime="12.5%" />
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="75%" />
                                    <LinearDoubleKeyFrame Value="0.5" KeyTime="100%" />
                                </DoubleAnimationUsingKeyFrames>
                             </Storyboard>
                         </BeginStoryboard>
                     </EventTrigger.Actions>
                 </EventTrigger>
             </Line.Triggers>
         </Line>

    <!-- And so on and so forth, 6 more times -->
    </Grid> 
</UserControl>

I didn't want to post the whole thing, that might just be too painful to look at, but you get the idea. The only thing changing from Line.Triggers to /Line.Triggers in each one is the BeginTime for the Storyboard. Is there a way in XAML that I can define that BeginTime in the Line, then read from it in the Storyboard, so I could do something closer to:

<UserControl.Resources>
    <!-- Try to read BeginTime from ancestral element -->
    <Storyboard x:Key="myStoryboard" RepeatBehavior="Forever" Duration="0:0:0.8"
                BeginTime="{Binding SomeSource, Property=StoryboardBeginTime}">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
            <LinearDoubleKeyFrame Value="0.5" KeyTime="0%" />
            <LinearDoubleKeyFrame Value="1.0" KeyTime="12.5%" />
            <LinearDoubleKeyFrame Value="0.5" KeyTime="75%" />
            <LinearDoubleKeyFrame Value="0.5" KeyTime="100%" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</UserControl.Resources>
    <!-- Try to send BeginTime to storyboard contained within -->
    <Line Blah="blah" StoryboardBeginTime="0:0:0.1">
        <Line.Triggers>
            <EventTrigger>
                <EventTrigger.Actions>
                    <BeginStoryboard Storyboard="{StaticResource myStoryboard}" />
                </EventTrigger.Actions>
            </EventTrigger>
        </Line.Triggers>
    </Line>

I just can't seem to track down if there's a way to do this in XAML, pass a storyboard a value for one of its properties from an element higher up the tree. Is this type of thing even possible, or should I do it in the code-behind instead? It's not exactly the most pleasant thing to do right now if I decide to tweak the animation at all.

Thanks!

Best Answer

it seems that this is not possible - though it might with 4.0, but I didn't test this. You can do this with code-behind.

-sa