ben Lim
ben Lim

Reputation: 33

Making Storyboards into resources that can be used by multiple controls in WPF

I have a working animation, now I am placing it in Apps.xaml under application.Resources, with all necessary bindings but it doesn't work. Am I missing something in the binding process? What is the proper way to bind the Storyboard.Targetname?

<Storyboard x:Key="RotateIn">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="button2">
                <EasingDoubleKeyFrame KeyTime="0" Value="-100"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="button2">
                <EasingDoubleKeyFrame KeyTime="0" Value="50"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="button2">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform" 
                                                 Storyboard.TargetProperty="Angle" 
                                                 By="10"        
                                                 To="360" 
                                                 Duration="0:0:0.7" 
                                                 FillBehavior="Stop" />
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="textBlock">
                <EasingDoubleKeyFrame KeyTime="0" Value="90"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
            </DoubleAnimationUsingKeyFrames>

        </Storyboard>
<Button Grid.Column="1" Name="btn2" Width="150" Height="150" Background="gray">
                <StackPanel >
                    <Image Source="{StaticResource img2}" x:Name="button2" RenderTransformOrigin=".5,.5">
                        <Image.RenderTransform>
                            <TransformGroup>
                                <ScaleTransform/>
                                <SkewTransform/>
                                <RotateTransform Angle="0" x:Name="AnimatedRotateTransform"/>
                                <TranslateTransform/>
                            </TransformGroup>
                        </Image.RenderTransform>
                    </Image>
                    <TextBlock x:Name="textBlock" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
                        <TextBlock.RenderTransform>
                            <TransformGroup>
                                <ScaleTransform/>
                                <SkewTransform/>
                                <RotateTransform/>
                                <TranslateTransform/>
                            </TransformGroup>
                        </TextBlock.RenderTransform>Rotate In</TextBlock>
                </StackPanel>
            </Button>

Above is my working animation created for a single Control. However, when I tried to make it into a resource where it can be reused like here , (H.B.)'s answer :

<Application.Resources>
        <ResourceDictionary>
            <Storyboard x:Key="BindingRotate" x:Shared="False">
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="{DynamicResource AnimationTarget}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="-100"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="{DynamicResource AnimationTarget}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="50"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="{DynamicResource AnimationTarget}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1"/>
                </DoubleAnimationUsingKeyFrames>
                <DoubleAnimation Storyboard.TargetName="{DynamicResource AnimationTarget1}"
                                                 Storyboard.TargetProperty="Angle" 
                                                 By="10"        
                                                 To="360" 
                                                 Duration="0:0:0.7" 
                                                 FillBehavior="Stop" />
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="{DynamicResource AnimationTarget2}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="90"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
                </DoubleAnimationUsingKeyFrames>

            </Storyboard>
        </ResourceDictionary>

    </Application.Resources>
<Button Grid.Column="1" Name="btn2" Width="150" Height="150" Background="gray">
                <StackPanel >
                    <Image Source="{StaticResource img2}" x:Name="button2" RenderTransformOrigin=".5,.5">
                        <Image.Resources>
                            <sys:String x:Key="AnimationTarget">button</sys:String>
                        </Image.Resources>
                        <Image.RenderTransform>
                            <TransformGroup>
                                <ScaleTransform/>
                                <SkewTransform/>
                                <RotateTransform Angle="0" x:Name="AnimationTarget1">

                                </RotateTransform>
                                <TranslateTransform/>
                            </TransformGroup>
                        </Image.RenderTransform>
                    </Image>
                    <TextBlock x:Name="textBlock" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5" Text="Rotate In">
                        <TextBlock HorizontalAlignment="Center" Text="Expand In">
                            <TextBlock.Resources>
                                <sys:String x:Key="AnimationTarget2">button</sys:String>
                            </TextBlock.Resources>
                        </TextBlock>
                    </TextBlock>
                </StackPanel>
                <Button.Triggers>
                    <EventTrigger RoutedEvent="ButtonBase.MouseEnter">
                        <BeginStoryboard Storyboard="{StaticResource BindingRotate}"/>
                    </EventTrigger>
                </Button.Triggers>
            </Button>

''[Unknown]' property does not point to a DependencyObject in path '(0).(1)[3].(2)'.'

Exception is all I get. I followed exactly what was stated in the answer. Please let me know what is missing in my binding as I could not find related topic.

Another question, is there any way for me to set

<sys:String x:Key="AnimationTarget1">button</sys:String>

into <RotateTransform.Resources> as I did to other controls? Thank you for your time. I am still quite new to WPF.

Upvotes: 3

Views: 266

Answers (1)

mm8
mm8

Reputation: 169270

Define the resources that you are referring to in your Storyboard, i.e. AnimationTarget, AnimationTarget1 and AnimationTarget2, in the Resources property of the Button where the EventTrigger is defined. This works for me:

<Button Grid.Column="1" Name="btn2" Width="150" Height="150" Background="gray">
    <Button.Resources>
        <sys:String x:Key="AnimationTarget">button2</sys:String>
        <sys:String x:Key="AnimationTarget1">AnimatedRotateTransform</sys:String>
        <sys:String x:Key="AnimationTarget2">button2</sys:String>
    </Button.Resources>
    <StackPanel >
        <Image Source="{StaticResource img2}" x:Name="button2" RenderTransformOrigin=".5,.5">
            <Image.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
                    <TranslateTransform/>
                </TransformGroup>
            </Image.RenderTransform>
        </Image>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5" Text="Rotate In">
            <TextBlock HorizontalAlignment="Center" Text="Expand In" />
        </TextBlock>
    </StackPanel>
    <Button.Triggers>
        <EventTrigger RoutedEvent="ButtonBase.MouseEnter">
            <BeginStoryboard Storyboard="{StaticResource BindingRotate}"/>
        </EventTrigger>
    </Button.Triggers>
</Button>

Upvotes: 1

Related Questions