我可以在ControlTemplate中对动画的持续时间使用数据绑定吗?

时间:2017-06-05 20:29:31

标签: wpf xaml data-binding

我在这里找到good explanation,了解如何将Duration的{​​{1}}属性绑定到ColorAnimation的{​​{1}}属性。一个使用转换器将滑块中的Value值转换为Slider,并使用Double设置Duration的{​​{1}}。这里,缩写,是如何工作的:

Binding

我试过了,它对我来说很好。但我想要做的是将Duration绑定到我添加到自定义控件中的名为ColorAnimation的依赖项属性。所以,在那个控件的<Window.Resources> <local:DoubleToDurationConverter x:Key="DoubleToDurationConverter" /> </Window.Resources> <Slider x:Name="slider" /> <Button Content="Click me for an animation"> <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <ColorAnimation To="Green" Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" FillBehavior="Stop" Duration="{Binding ElementName=slider, Path=Value, Mode=OneWay, Converter={StaticResource DoubleToDurationConverter}}" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> 我有这个:

Duration

这是编译,但在运行时给我一条错误消息:

  

InvalidOperationException:无法冻结此Storyboard时间轴树   用于跨线程。

如何将FadeTime的{​​{1}}绑定到自定义控件ControlTemplate中的依赖变量?

谢谢!

更新

对于我想要做的事情,数据绑定实际上是一种过度杀伤力。真正的数据绑定将允许属性的值在运行时更改。我真正想要的只是让使用我的自定义控件的开发人员能够在设计时设置<ControlTemplate.Triggers> <Trigger Property="IsLit" Value="true"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="glow" Storyboard.TargetProperty="Opacity" To="1" Duration="{Binding FadeTime, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> </Trigger> </ControlTemplate.Triggers> 的{​​{1}},而无需编辑DoubleAnimation。如果开发人员选择的值在运行时永远不会改变,那也没关系。

2 个答案:

答案 0 :(得分:1)

基本上,您无法在控件模板的故事板中使用常规绑定。由于您只想让开发人员更改值,因此以下选项之一可能对您有用:

(1)使用StaticResource:将持续时间对象放在控件模板之外的某个位置,以便开发人员更容易更改。但是,它需要在控件模板上静态访问,因为DynamicResource不会在这个地方工作。

<Duration x:Key="MyCustomDuration">0:0:1</Duration>
... then later
Duration="{StaticResource MyCustomDuration}"

(2)在x:Static

的字段后面使用静态代码
public static class SettingsClass
{
    public static Duration MyCustomDuration = new Duration(new TimeSpan(0, 0, 1));
}

并使用:

Duration="{x:Static local:SettingsClass.MyCustomDuration}"

答案 1 :(得分:1)

您可以在PropertyChangedCallback IsLit属性中以编程方式定义XAML标记中的动画,而不是在XAML标记中定义动画。

您可以简单地定义另一个属性,让控件的使用者指定动画的持续时间。

这是一个例子。

<强>控制:

public class MyCustomControl : Control
{
    private UIElement glow;

    public static readonly DependencyProperty DurationProperty =
         DependencyProperty.Register("Duration", typeof(TimeSpan),
         typeof(MyCustomControl), new PropertyMetadata(TimeSpan.FromSeconds(1)));

    public TimeSpan Duration
    {
        get { return (TimeSpan)GetValue(DurationProperty); }
        set { SetValue(DurationProperty, value); }
    }

    public static readonly DependencyProperty IsLitProperty =
         DependencyProperty.Register("IsLit", typeof(bool),
         typeof(MyCustomControl), new PropertyMetadata(false, new PropertyChangedCallback(OnIsLitChanged)));

    public bool IsLit
    {
        get { return (bool)GetValue(IsLitProperty); }
        set { SetValue(IsLitProperty, value); }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        glow = Template.FindName("glow", this) as UIElement;
        if (glow != null && IsLit)
            Animate(glow);

    }

    private static void OnIsLitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        bool newValue = (bool)e.NewValue;
        if(newValue)
        {
            MyCustomControl c = d as MyCustomControl;
            if(c != null && c.glow != null)
            {
                c.Animate(c.glow);
            }
        }
    }

    private void Animate(UIElement glow)
    {
        DoubleAnimation animation = new DoubleAnimation();
        animation.To = 1;
        animation.Duration = Duration;
        glow.BeginAnimation(OpacityProperty, animation);
    }
}

<强>模板:

<ControlTemplate x:Key="ct" TargetType="local:MyCustomControl">
    <Border x:Name="glow" Width="100" Height="100" Background="Red" Opacity="0.1">
    </Border>
</ControlTemplate>

<强>用法:

<local:MyCustomControl Template="{StaticResource ct}" Duration="0:0:5" IsLit="True" />