CurtisHx
CurtisHx

Reputation: 758

Using a DataTrigger to start an animation that requires a dynamic value

I have an animation that moves a border (using a render translate transform) to it's width. This animation needs to be applied to multiple borders, and those borders will vary in width. So I bound the Value property of the animation keyframe to to ActualWidth of the border, so it slides out.

Trying to run this code will yield a an exception with the message: Cannot freeze this Storyboard timeline tree for use across threads.

Hard coding a value for the Value property of the key frame fixes this problem, but then the animation either goes too far, or not far enough.

Here's some example code that shows what I'm trying to accomplish.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1" xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="WpfApplication1.MainWindow"
    Title="MainWindow" Height="350" Width="525">
<Grid >
  <Button Content="Show Menu" HorizontalAlignment="Left" Margin="270,30,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Click="Button_Click"/>

  <Border x:Name="border" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="100" Margin="260,108,0,0" VerticalAlignment="Top" Width="100" RenderTransformOrigin="0.5,0.5">
     <Border.Style>
        <Style>
           <Style.Resources>
              <Storyboard x:Key="SlideOut">
                 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border">
                    <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="{Binding ActualWidth, ElementName=border}"/>
                 </DoubleAnimationUsingKeyFrames>
              </Storyboard>
              <Storyboard x:Key="SlideIn">
                 <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border">
                    <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
                 </DoubleAnimationUsingKeyFrames>
              </Storyboard>
           </Style.Resources>
        <Style.Triggers>
              <DataTrigger Binding="{Binding IsMenuOpen}" Value="True">
                 <DataTrigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource SlideOut}"/>
                 </DataTrigger.EnterActions>
                 <DataTrigger.ExitActions>
                    <BeginStoryboard Storyboard="{StaticResource SlideIn}"/>
                 </DataTrigger.ExitActions>
              </DataTrigger>
           </Style.Triggers>
        </Style>
     </Border.Style>
        <Border.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform/>
                <TranslateTransform/>
            </TransformGroup>
        </Border.RenderTransform>
        <Border.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Black" Offset="0"/>
                <GradientStop Color="White" Offset="1"/>
            </LinearGradientBrush>
        </Border.Background>
    </Border>
</Grid>
</Window>

Upvotes: 3

Views: 2153

Answers (2)

eran otzap
eran otzap

Reputation: 12533

I'm not sure that the error your getting is the actual cuase but more of a problem derived from the original problem

try :

  <Storyboard x:Key="SlideOut">
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border">
        <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="{Binding ActualWidth, RelativeSource={RelativeSource Self}}"/>
    </DoubleAnimationUsingKeyFrames>
 </Storyboard>

It does not make sense to me that you can refer to an object to itself by ElementName .

Upvotes: 0

Vinkal
Vinkal

Reputation: 2984

You are using Binding in Storyboard. You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. That's because everything inside a Style must be thread-safe, and the timing system must Freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions.

EDIT This Link has the solution.

Upvotes: 2

Related Questions