我有一个控件,我想要为只读DependencyProperty
使用像这样的香草动画不起作用(按预期):
var animation = new DoubleAnimation(value, TimeSpan.FromMilliseconds(100));
this.BeginAnimation(SomeValueProperty, animation);
猜猜我正在寻找类似的东西:
var animation = new DoubleAnimation(value, TimeSpan.FromMilliseconds(100));
this.BeginAnimation(SomeValuePropertyKey, animation);
是否有一种使用框架动画我的属性的简洁方法?
答案 0 :(得分:2)
找到一个〜聪明的解决方案:
public class DummyControl : Control
{
internal static readonly DependencyPropertyKey SomePropPropertyKey = DependencyProperty.RegisterReadOnly(
"SomeProp",
typeof(double),
typeof(DummyControl),
new PropertyMetadata(0.0));
// A proxy that is used for animating. Sets the value of the readonly property on change.
private static readonly DependencyProperty SomePropProxyProperty = DependencyProperty.Register(
"SomePropProxy",
typeof(double),
typeof(DummyControl),
new PropertyMetadata(0.0, OnSomePropProxyChanged));
public static readonly DependencyProperty SomePropProperty = SomePropPropertyKey.DependencyProperty;
public double SomeProp
{
get { return (double)this.GetValue(SomePropProperty); }
protected set { this.SetValue(SomePropPropertyKey, value); }
}
public void AnimateTo(double value)
{
var animation = new DoubleAnimation(value, TimeSpan.FromMilliseconds(100));
this.BeginAnimation(SomePropProxyProperty, animation);
// We are animating the proxy here.
}
private static void OnSomePropProxyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.SetValue(SomePropPropertyKey, e.NewValue);
// Updating the value of the readonly property here.
}
}
这不是一个非常干净的解决方案,但它至少使用标准动画。请提出更好的建议!
答案 1 :(得分:1)
公开代理属性是一种解决方案,但令人毛骨悚然的是,这制动了无用的只读限制。更好的方法是创建一个代理对象。这将使动画属性只能在您正在编写的控件内访问。
public class AnimationProxy<T> : Animatable
{
private Action<T> _valueUpdateCallback;
#region AnimatableProperty
public static readonly DependencyProperty AnimatablePropertyProperty =
DependencyProperty.Register("AnimatableProperty", typeof(T), typeof(AnimationProxy<T>),
new FrameworkPropertyMetadata(default(T),
new PropertyChangedCallback(OnAnimatablePropertyChanged)));
public T AnimatableProperty
{
get { return (T)GetValue(AnimatablePropertyProperty); }
set { SetValue(AnimatablePropertyProperty, value); }
}
private static void OnAnimatablePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AnimationProxy<T> target = (AnimationProxy<T>)d;
T oldAnimatableProperty = (T)e.OldValue;
T newAnimatableProperty = target.AnimatableProperty;
target.OnAnimatablePropertyChanged(oldAnimatableProperty, newAnimatableProperty);
}
protected virtual void OnAnimatablePropertyChanged(T oldAnimatableProperty, T newAnimatableProperty)
{
_valueUpdateCallback?.Invoke(newAnimatableProperty);
}
#endregion
public AnimationProxy(Action<T> valueUpdateCallback)
{
_valueUpdateCallback = valueUpdateCallback;
}
//Override to keep compiler happy
protected override Freezable CreateInstanceCore()
{
throw new NotImplementedException();
}
}
所以现在要设置readonly属性的动画,您只需提供回调并为代理对象设置动画:
var animationProxy = new AnimationProxy<double>(SetReadOnlyProperty);
animationProxy.AnimatableProperty = ReadOnlyProperty;
var animation = new DoubleAnimation(0, new Duration(CurrentTimeLeft));
animationProxy.BeginAnimation(AnimationProxy<double>.AnimatablePropertyProperty, animation);
答案 2 :(得分:-1)
尝试这样的事情:
DoubleAnimation anim = new DoubleAnimation()
{
From = 0,
To = 200,
Duration = TimeSpan.FromMilliseconds(600),
DecelerationRatio = 1
};
anim.Completed += (objAnim, eAnim) =>
{
//Do something when animation completed
};
yourControl.BeginAnimation(Canvas.LeftProperty, anim);