我的问题:
它必须是附加属性吗?使用 Behavior 可以吗?
- 有没有办法通过绑定取消 Opacity 属性立即更改并改为运行动画?
也许有一些技巧(据我所知没有)。再次,这是必须拦截和取消正常 DP 操作的必要条件吗?
- 任何指向示例的链接都将受到高度赞赏,因为我自己找不到任何链接。
如果你能稍微调整一下你的要求,我可以举个例子:
因此,如果您的要求是在绑定到值更改时为任何 double DP 设置动画,我们可以使用 Behavior
public class AnimateBehavior : Behavior<UIElement> {
public static readonly DependencyProperty ToAnimateProperty =
DependencyProperty.Register("ToAnimate", typeof(DependencyProperty),
typeof(AnimateBehavior), new FrameworkPropertyMetadata(null));
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double),
typeof(AnimateBehavior),
new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.None, ValueChangedCallback));
public DependencyProperty ToAnimate {
get { return (DependencyProperty) GetValue(ToAnimateProperty); }
set { SetValue(ToAnimateProperty, value); }
}
public double Value {
get { return (double) GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var item = d as AnimateBehavior;
if (item == null || item.AssociatedObject == null) {
return;
}
var newAnimation = new DoubleAnimation((double) e.NewValue, new Duration(new TimeSpan(0, 0, 1)));
item.AssociatedObject.BeginAnimation(item.ToAnimate, newAnimation);
}
}
现在在 xaml 中:
<TextBlock Text="Hello">
<i:Interaction.Behaviors>
<local:AnimateBehavior ToAnimate="{x:Static TextBlock.OpacityProperty}" Value="{Binding ValueYouWantToBindToOpacity}" />
</i:Interaction.Behaviors>
</TextBlock>
现在使用这种方法,您可以为该控件的任何具有双精度类型值的 DP 设置动画。喜欢Opacity、FontSize ...
这里与您的原始要求的主要区别是我们不将Value 绑定到元素。相反,我们将其绑定到Behavior。现在,当这种情况发生变化时,我们会在行为中检测到它,并通过行为的 AssociatedObject 属性,将动画应用于实际项目。
我们还通过提供属性在值通过 DP 更改为行为时进行动画处理来满足您满足多种双 DP 类型的要求。
如果您想要更通用,您可以使 Behavior 也接受持续时间和动画类型,使其更通用。
替代 DP 识别属性:
如果您绝对想传入“不透明度”而不是 DP,请尝试以下操作:
public static readonly DependencyProperty ToAnimateProperty =
DependencyProperty.Register("ToAnimate", typeof(PropertyPath),
typeof(AnimateBehavior), new FrameworkPropertyMetadata(null));
public PropertyPath ToAnimate
{
get { return (PropertyPath)GetValue(ToAnimateProperty); }
set { SetValue(ToAnimateProperty, value); }
}
所以我们将ToAnimate 设为PropertyPath
在ValueChanged函数中
private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var item = d as AnimateBehavior;
if (item == null || item.AssociatedObject == null) {
return;
}
var sb = new Storyboard();
var newAnimation = new DoubleAnimation((double) e.NewValue, new Duration(new TimeSpan(0, 0, 1)));
Storyboard.SetTarget(newAnimation, item.AssociatedObject);
Storyboard.SetTargetProperty(newAnimation, item.ToAnimate);
sb.Children.Add(newAnimation);
sb.Begin();
}
我们创建一个Storyboard 并使用PropertyPath,您可以拥有:
<TextBlock Text="Hello">
<i:Interaction.Behaviors>
<local:AnimateBehavior ToAnimate="Opacity" Value="{Binding ValueYouWantToBindToOpacity}" />
</i:Interaction.Behaviors>
</TextBlock>
我仍然更喜欢 DP 而不是这种方法。