(这是尝试以不同的方式解决my earlier problem。)
我创建了一个用户控件,它使用RadialGradientBrush,我希望能够通过在我的视图模型上设置属性来设置动画。渐变画笔还具有一些绑定到视图模型的属性。
用户控件的XAML是(为简洁起见,剪切了一些属性):
<UserControl x:Class="WpfApplication1.AnimatedLineArrow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Controls="clr-namespace:Microsoft.Expression.Controls;assembly=Microsoft.Expression.Drawing"
mc:Ignorable="d" d:DesignHeight="150" d:DesignWidth="300"
Name="animatedLineArrow">
<Grid>
<Controls:LineArrow x:Name="ArrowControl"
StartCorner="{Binding ElementName=animatedLineArrow, Path=StartCorner, FallbackValue=TopRight}"
Width="{Binding ElementName=animatedLineArrow, Path=Width, FallbackValue=200}"
Height="{Binding ElementName=animatedLineArrow, Path=Height, FallbackValue=200}"
<Controls:LineArrow.Stroke>
<RadialGradientBrush RadiusX="0.2" RadiusY="1.0"
Center="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}"
GradientOrigin="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}">
<RadialGradientBrush.GradientStops>
<GradientStop Color="{Binding ElementName=animatedLineArrow, Path=HighlightColour, Mode=OneWay, FallbackValue=Cyan}" Offset="0.0" />
<GradientStop Color="{Binding ElementName=animatedLineArrow, Path=PrimaryColour, Mode=OneWay, FallbackValue=Navy}" Offset="1.0" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Controls:LineArrow.Stroke>
</Controls:LineArrow>
</Grid>
</UserControl>
代码隐藏设置各种依赖项属性,并在控件的Loaded事件中定义一个Storyboard来为RadialGradientBrush的Center和GradientOrigin属性设置动画,然后定义应该响应其中一个依赖项属性值的DataTriggers :
private void ConfigureAnimation(object sender, EventArgs e)
{
StartPoint = StartingPoints[StartCorner];
EndPoint = EndingPoints[StartCorner];
AnimatedLineArrow arrow = (AnimatedLineArrow)sender;
Storyboard storyboard = CreateStoryboard(arrow);
DataTrigger startTrigger = new DataTrigger
{
Binding = new Binding
{
Path = new PropertyPath(IsRunningProperty),
RelativeSource = RelativeSource.Self
},
Value = true
};
startTrigger.EnterActions.Add(new BeginStoryboard { Storyboard = storyboard, Name = "beginStoryboard" });
DataTrigger endTrigger = new DataTrigger
{
Binding = new Binding
{
Path = new PropertyPath(IsRunningProperty),
RelativeSource = RelativeSource.Self
},
Value = false
};
endTrigger.EnterActions.Add(new StopStoryboard { BeginStoryboardName = "beginStoryboard" });
Style style = new Style(typeof(AnimatedLineArrow));
style.Triggers.Add(startTrigger);
style.Triggers.Add(endTrigger);
arrow.Style = style;
}
private Storyboard CreateStoryboard(AnimatedLineArrow arrow)
{
Storyboard storyboard = new Storyboard();
PointAnimation originAnimation = new PointAnimation(StartingPoints[StartCorner], EndingPoints[StartCorner], Duration, FillBehavior.HoldEnd);
PointAnimation centreAnimation = originAnimation.Clone();
Storyboard.SetTarget(originAnimation, arrow);
Storyboard.SetTargetProperty(originAnimation, new PropertyPath(RadialGradientBrush.GradientOriginProperty));
Storyboard.SetTarget(centreAnimation, arrow);
Storyboard.SetTargetProperty(centreAnimation, new PropertyPath(RadialGradientBrush.CenterProperty));
storyboard.Children.Add(originAnimation);
storyboard.Children.Add(centreAnimation);
return storyboard;
}
当我尝试运行项目时,它成功编译并且窗口成功加载,控件处于默认状态。但是,当DataTrigger第一次触发时,我得到以下异常:
System.InvalidOperationException was unhandled
Message='beginStoryboard' name cannot be found in the name scope of 'System.Windows.Style'.
Source=PresentationFramework
我附上了一个示例项目to demonstrate what I am trying to achieve。
答案 0 :(得分:2)
您似乎需要使用Style.RegisterName注册BeginStoryboard的名称。类似的东西:
//...
BeginStoryboard bs = new BeginStoryboard { Storyboard = storyboard, Name = "beginStoryboard" };
startTrigger.EnterActions.Add(bs);
//...
style.RegisterName(bs.Name, bs);
对于动画/故事板,您实际上是在尝试为AnimatedLineArrow上的RadialGradientBrush属性设置动画(而不是在实际的RadialGradientBrush上)。您需要将故事板目标设置为RadialGradientBrush,或者在AnimatedLineArrow上公开可以设置动画的其他属性。
类似的东西:
public static readonly DependencyProperty AnimatedPointProperty = DependencyProperty.Register("AnimatedPoint",
typeof(Point), typeof(AnimatedLineArrow), new FrameworkPropertyMetadata(new Point()));
public Point AnimatedPoint {
get { return (Point)this.GetValue(AnimatedLineArrow.AnimatedPointProperty); }
set { this.SetValue(AnimatedLineArrow.AnimatedPointProperty, value); }
}
private Storyboard CreateStoryboard(AnimatedLineArrow arrow)
{
Storyboard storyboard = new Storyboard();
PointAnimation originAnimation = new PointAnimation(StartingPoints[StartCorner], EndingPoints[StartCorner], Duration, FillBehavior.HoldEnd);
Storyboard.SetTarget(originAnimation, arrow);
Storyboard.SetTargetProperty(originAnimation, new PropertyPath(AnimatedPointProperty));
storyboard.Children.Add(originAnimation);
return storyboard;
}
然后在AnimatedLineArrow.xaml中,你需要使用:
<RadialGradientBrush RadiusX="0.2" RadiusY="1.0"
Center="{Binding ElementName=animatedLineArrow, Path=StartPoint, Mode=OneWay}"
GradientOrigin="{Binding ElementName=animatedLineArrow, Path=AnimatedPoint, Mode=OneWay}">
<RadialGradientBrush.GradientStops>
<GradientStop Color="{Binding ElementName=animatedLineArrow, Path=HighlightColour, Mode=OneWay, FallbackValue=Cyan}" Offset="0.0" />
<GradientStop Color="{Binding ElementName=animatedLineArrow, Path=PrimaryColour, Mode=OneWay, FallbackValue=Navy}" Offset="1.0" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>