使用DataTrigger启动需要动态值的动画

时间:2015-02-10 15:39:53

标签: wpf animation mvvm .net-4.5 datatrigger

我有一个动画可以将边框(使用渲染平移变换)移动到它的宽度。此动画需要应用于多个边框,并且这些边框的宽度会有所不同。因此,我将动画关键帧的Value属性绑定到边框的ActualWidth,以便滑出。

尝试运行此代码会产生一条例外消息:Cannot freeze this Storyboard timeline tree for use across threads.

对关键帧的Value属性进行硬编码可以解决这个问题,但是动画要么走得太远,要么不够远。

这是一些示例代码,显示了我想要完成的任务。

<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>

2 个答案:

答案 0 :(得分:2)

您在Binding中使用Storyboard。您无法使用动态资源引用数据绑定表达式来设置Storyboard或动画属性值。这是因为Style中的所有内容都必须为thread-safe,并且计时系统必须冻结Storyboard个对象才能使它们成为thread-safe。如果Storyboard或其子时间轴包含动态资源引用或数据binding表达式,则无法冻结{<1}}。

编辑Link有解决方案。

答案 1 :(得分:0)

我不确定你得到的错误是实际的问题,但更多是从原始问题中得出的问题

尝试:

  <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>

对我来说,你可以通过 ElementName 引用一个对象是没有意义的。