WPF UserControl中Storyboard的Duration属性动态绑定问题
问题根因
绑定失效是WPF资源对象的特性导致的:放在UserControl.Resources里的Storyboard属于Freezable类型资源,默认不在可视化逻辑树中,ElementName绑定需要在同一个名称作用域下才能解析到目标元素,因此找不到你定义的thisControl实例,绑定自然无法生效。
可行解决方案
方案1:后台代码手动赋值(最稳定,无绑定失效问题)
你可以在触发动画执行的逻辑前,手动获取资源中的Storyboard,给对应动画属性赋值,同时可以同步修改布尔动画的时长和关键帧时间,避免两个动画节奏不一致:
// 触发动画的逻辑处添加如下代码 var progressSb = (Storyboard)FindResource("ProgressBarAnimation"); // 给路径动画赋值时长 var pointAnim = (PointAnimationUsingPath)progressSb.Children[0]; pointAnim.Duration = D1; // 同步修改布尔关键帧动画的时长和中间切换时间 var boolAnim = (BooleanAnimationUsingKeyFrames)progressSb.Children[1]; boolAnim.Duration = D1; // 中间切换时间设为总时长的一半,保持原逻辑 ((DiscreteBooleanKeyFrame)boolAnim.KeyFrames[1]).KeyTime = KeyTime.FromTimeSpan(D1.TimeSpan / 2); // 启动动画 progressSb.Begin();
同时把依赖属性改成Duration类型,避免类型转换问题:
public partial class usercontrol : UserControl { public Duration D1 { get { return (Duration)GetValue(D1Property); } set { SetValue(D1Property, value); } } public static readonly DependencyProperty D1Property = DependencyProperty.Register("D1", typeof(Duration), typeof(usercontrol), new PropertyMetadata(new Duration(TimeSpan.FromSeconds(40)))); public usercontrol() { InitializeComponent(); } }
方案2:调整XAML绑定方式
不想写后台赋值逻辑的话,把绑定改成用RelativeSource查找父级UserControl,跳过ElementName的名称作用域限制即可:
<PointAnimationUsingPath Storyboard.TargetProperty="Point" Duration="{Binding D1, RelativeSource={RelativeSource AncestorType=UserControl}}">
如果同时要动态调整布尔关键帧动画的属性,用同样的绑定方式即可,需要动态修改KeyTime的话补充一个简单的IValueConverter实现TimeSpan到KeyTime的转换即可。
内容的提问来源于stack exchange,提问作者Eduardo Silva
相关产品推荐
相关产品推荐

