Storyboard不会为自定义FrameworkElement属性设置动画

时间:2013-01-05 16:07:05

标签: c# wpf animation storyboard

我的类派生自FrameworkElement,我希望WPF使用DoubleAnimation更新其Location属性。我将该房产注册为DependendencyProperty

public class TimeCursor : FrameworkElement
{
    public static readonly DependencyProperty LocationProperty;

    public double Location
    {
        get { return (double)GetValue(LocationProperty); }
        set
        {
            SetValue(LocationProperty, value);
        }
    }

    static TimeCursor()
    {
        LocationProperty = DependencyProperty.Register("Location", typeof(double), typeof(TimeCursor));
    }
}

以下代码设置了故事板。

TimeCursor timeCursor;
private void SetCursorAnimation()
{
    timeCursor = new TimeCursor();
    NameScope.SetNameScope(this, new NameScope());
    RegisterName("TimeCursor", timeCursor);

    storyboard.Children.Clear();

    DoubleAnimation animation = new DoubleAnimation(LeftOffset, LeftOffset + (VerticalLineCount - 1) * HorizontalGap + VerticalLineThickness, 
                new Duration(TimeSpan.FromMilliseconds(musicDuration)), FillBehavior.HoldEnd);

    Storyboard.SetTargetName(animation, "TimeCursor");
    Storyboard.SetTargetProperty(animation, new PropertyPath(TimeCursor.LocationProperty));

    storyboard.Children.Add(animation);
}

然后我从包含上述storyboard.Begin(this)方法的对象的另一个方法中调用SetCursorAnimation(),该对象派生自Canvas。但是Location属性永远不会更新(从不调用Location的set访问器)并且不会抛出异常。我做错了什么?

1 个答案:

答案 0 :(得分:1)

当依赖项属性被动画化(或在XAML中设置,或由样式设置器等设置)时,WPF不会调用CLR包装器,而是直接访问底层的DependencyObject和DependencyProperty对象。请参阅Checklist for Defining a Dependency Property中的实施“包装器”部分以及Implications for Custom Dependency Properties

要获得有关房产更改的通知,您必须注册PropertyChangedCallback

public class TimeCursor : FrameworkElement
{
    public static readonly DependencyProperty LocationProperty =
        DependencyProperty.Register(
            "Location", typeof(double), typeof(TimeCursor),
            new FrameworkPropertyMetadata(LocationPropertyChanged)); // register callback here

    public double Location
    {
        get { return (double)GetValue(LocationProperty); }
        set { SetValue(LocationProperty, value); }
    }

    private static void LocationPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var timeCursor = obj as TimeCursor;

        // handle Location property changes here
        ...
    }
}

另请注意,为依赖项属性设置动画并不一定需要Storyboard。您只需在TimeCursor实例上调用BeginAnimation方法:

var animation = new DoubleAnimation(LeftOffset,
    LeftOffset + (VerticalLineCount - 1) * HorizontalGap + VerticalLineThickness, 
    new Duration(TimeSpan.FromMilliseconds(musicDuration)),
    FillBehavior.HoldEnd);

timeCursor.BeginAnimation(TimeCursor.LocationProperty, animation);