Search code examples
wpfxamlanimationstoryboarddatatrigger

How can I stop a custom storyboard with a data trigger?


I have a storyboard for a canvas and I want to stop it as soon as the ShowError property has changed.

 <UserControl.Resources>
        <Storyboard x:Key="LoaderAnimation" Name="LoaderAnimation" >
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" 
                                           Storyboard.TargetName="canvas" 
                                           RepeatBehavior="Forever">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:3" Value="360"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>


        <Viewbox x:Name="LayoutRoot" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="0" Height="150" Width="250">
            <Canvas Height="323" Width="308" RenderTransformOrigin="0.5,0.5" x:Name="canvas">
                <Canvas.RenderTransform>
                    <RotateTransform/>
                </Canvas.RenderTransform>

                <Ellipse Fill="{Binding Foreground, ElementName=userControl}" Height="71" Canvas.Left="121" Canvas.Top="21" Width="69" Opacity="0.3"/>
                <Ellipse Fill="{Binding Foreground, ElementName=userControl}" Height="71" Width="69" Canvas.Left="194" Canvas.Top="52" Opacity="0.4"/>
                <Ellipse Fill="{Binding Foreground, ElementName=userControl}" Width="69" Height="71" 

            </Canvas>
        </Viewbox>

        <TextBlock Grid.Row="1" TextWrapping="Wrap" FontSize="20" Margin="0 20 0 0">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ShowError}" Value="false">
                            <Setter Property="Text" Value="{loc:Translate LogIn.TestSpsConnection}" />
                            <Setter Property="Foreground" Value="Black" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding ShowError}" Value="true">
                            <Setter Property="Text" Value="{loc:Translate LogIn.FailSpsConnection}" />
                            <Setter Property="Foreground" Value="Red" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
        
    </Grid>

I've tried every idea but I can't access the storyboard from the style of the TextBlock. Is there any way I can stop the animation when ShowError goes true ? thank you for your help


Solution

  • Try applying a style trigger onto your Canvas that stops the storyboard when ShowError goes true, instead of doing it from your TextBlock.

    Example:

       <UserControl.Resources>
            <Storyboard x:Key="LoaderAnimation" Name="LoaderAnimation" >
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" 
                                               RepeatBehavior="Forever">
                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="360"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
        </UserControl.Resources>
    
    ...
    
    <Canvas Height="323" Width="308" RenderTransformOrigin="0.5,0.5" x:Name="canvas">
        ...
        <Canvas.Style>
            <Style TargetType="Canvas">
                <Style.Triggers>
                    <EventTrigger RoutedEvent="Loaded">
                        <EventTrigger.Actions>
                            <BeginStoryboard x:Name="beginStoryboard" Storyboard="{StaticResource LoaderAnimation}"/>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <DataTrigger Binding="{Binding ShowError}" Value="True">
                        <DataTrigger.EnterActions>
                            <StopStoryboard BeginStoryboardName="beginStoryboard"/>
                        </DataTrigger.EnterActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Canvas.Style>
    </Canvas>
    
    

    Also, notice that I removed the Storyboard.TargetName from your resource, or else it violates some XAML rules when used the way that I did it. You'll get runtime errors if you keep it there.