WPF故事板动画。无法数据绑定到SeekStoryboard Offset。需要想法

时间:2013-02-23 21:56:21

标签: wpf storyboard

我创建了一个用于ListBoxItems的DataTemplate。我创建了一个颜色动画,其中项目的背景颜色从绿色开始,并在一段时间内慢慢变为红色。

问题是这个 - 我需要设置Storyboard Seek Offset取决于ListBox项目中包含的时间戳(例如:一个项目突然填充ListBox,其颜色动画应移动,比如,17秒进入动画)。当我最初创建这个时,我认为这很容易,因为我只是将Offset绑定到一个值转换器,该转换器根据绑定项的时间戳返回TimeSpan值。但是,正如我发现的那样,您无法对SeekStoryboard Offset执行数据绑定。

任何人都可以建议一个解决方法或者一些代码隐藏魔法可以解决这个问题吗?此列表框将包含非常少的项目(最多可能是5个),因此遍历集合并以编程方式获取Storyboard资源并手动设置偏移量不会太耗时。但是,我不知道如何执行此操作,因为我的Listbox是由自定义对象填充的,而不是ListBoxItem类型的UIElement。

    <DataTemplate x:Key="TicketTemplate">
        <DataTemplate.Resources>
            <Storyboard x:Key="OnLoaded1">
                <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="border">
                    <EasingColorKeyFrame KeyTime="0" Value="Lime"/>
                    <EasingColorKeyFrame KeyTime="0:15:0" Value="Yellow"/>
                    <EasingColorKeyFrame KeyTime="0:30:0" Value="Orange"/>
                    <EasingColorKeyFrame KeyTime="0:45:0" Value="Red"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </DataTemplate.Resources>
        <Border x:Name="border" BorderBrush="Black" Margin="1" BorderThickness="2" CornerRadius="10" Padding="5,1">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="GhostWhite"  Offset="1"/>
                    <GradientStop Color="GhostWhite"/>
                </LinearGradientBrush>
            </Border.Background>
            <Grid>
                <!-- ELEMENTS FOR LISTBOXITEM TEMPLATE -->
            </Grid>
        </Border>
        <DataTemplate.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="border">
                <BeginStoryboard x:Name="WarningStory" Storyboard="{StaticResource OnLoaded1}"/>
                <SeekStoryboard BeginStoryboardName="WarningStory" Offset="0" <!-- cannot databind to Offset =( --> Origin="BeginTime" />
            </EventTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>

1 个答案:

答案 0 :(得分:2)

有一种解决方法可以启用绑定到不是依赖项属性的属性。它要求拥有target属性的类派生自DependencyObject,幸运的是SeekStoryboard

您将使用attached创建一个PropertyChangedCallback辅助属性,用于设置实际的目标属性。

public static class SeekStoryboardExt
{
    public static readonly DependencyProperty BindableOffsetProperty =
        DependencyProperty.RegisterAttached(
            "BindableOffset", typeof(TimeSpan), typeof(SeekStoryboardExt),
            new PropertyMetadata(BindableOffsetPropertyChanged));

    public static TimeSpan GetBindableOffset(DependencyObject obj)
    {
        return (TimeSpan)obj.GetValue(BindableOffsetProperty);
    }

    public static void SetBindableOffset(DependencyObject obj, TimeSpan value)
    {
        obj.SetValue(BindableOffsetProperty, value);
    }

    private static void BindableOffsetPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var seekStoryboard = obj as SeekStoryboard;
        if (seekStoryboard != null)
        {
            seekStoryboard.Offset = (TimeSpan)e.NewValue;
        }
    }
}

现在绑定helper属性而不是target属性:

<SeekStoryboard local:SeekStoryboardExt.BindableOffset="{Binding ...}" .../>