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

3

我有一个动画,它使用渲染平移变换将边框移动到其宽度。此动画需要应用于多个边框,并且这些边框的宽度将不同。因此,我将动画关键帧的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个回答

2
您正在使用Storyboard中的Binding。您不能使用动态资源引用数据绑定表达式来设置Storyboard或动画属性值。这是因为Style内的所有内容都必须是线程安全的,并且计时系统必须冻结Storyboard对象以使它们线程安全。如果一个Storyboard或其子时间轴包含动态资源引用或数据binding表达式,则无法冻结Storyboard

编辑链接提供了解决方案。


有没有办法绕过这个限制? - CurtisHx
刚才我已经更新了答案并提供了新链接。它有关于这种问题的详细解决方案。如果它对你有用,请告诉我。 - Vinkal

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来引用对象本身是没有意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接