Storyboard没有动画自定义FrameworkElement属性
本文关键字:FrameworkElement 属性 自定义 动画 Storyboard | 更新日期: 2023-09-27 17:50:43
我有一个来自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);
}
然后我从包含上述SetCursorAnimation()
方法的对象的另一个方法调用storyboard.Begin(this)
,该对象派生自Canvas
。然而,Location
属性永远不会更新(永远不会调用Location的set accessor),也不会抛出异常。我做错了什么?
当一个依赖属性被动画化(或者在XAML中设置,或者由Style Setter等设置)时,WPF不会调用CLR包装器,而是直接访问底层的DependencyObject和DependencyProperty对象。参见实现"包装器"一节,在定义依赖属性的清单和自定义依赖属性的含义。
为了获得关于属性更改的通知,您必须注册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
...
}
}
还要注意,动画化依赖属性并不一定需要一个故事板。你可以简单地调用TimeCursor实例上的BeginAnimation方法:
var animation = new DoubleAnimation(LeftOffset,
LeftOffset + (VerticalLineCount - 1) * HorizontalGap + VerticalLineThickness,
new Duration(TimeSpan.FromMilliseconds(musicDuration)),
FillBehavior.HoldEnd);
timeCursor.BeginAnimation(TimeCursor.LocationProperty, animation);