Storyboard.TargetProperty的设置应该是动画中的一个关键了,因为如果此属性设置错误(语法错误,或者是由于设置元素没有初始化此属性),不仅没有动画效果,反而出现错误。
设置 Storyboard.TargetProperty有三种方式(个人总结理解)
1.依赖属性的设置(直接使用属性)
<DoubleAnimation Storyboard.TargetName="myRec" Storyboard.TargetProperty="Width" From="100" To="200"></DoubleAnimation>
2.附加属性的设置(也是直接使用附加属性,需要加上括号)
<DoubleAnimation Storyboard.TargetName="myRec" Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="20" ></DoubleAnimation>
3.间接目标
有时动画不能直接以 Freezable(是Brush等对象的基类,当复制或者修改对象的时候开销很大,提高性能) 为目标,例如当 Freezable 声明为资源或者用于设置样式中的属性值时。 在这些情况下,即使不能直接将 Freezable 对象作为目标,您仍可以对其进行动画处理。 您可以为 TargetName 属性分配 Freezable“所属”的元素的名称,而不是使用 Freezable 的名称来设置该属性。例如,SolidColorBrush 用于设置矩形元素的 Fill 属于该矩形。 若要对该画笔进行动画处理,需要使用一个属性链来设置动画的 TargetProperty,这些属性起始于使用 Freezable 设置的框架元素或框架内容元素的属性,结束于要进行动画处理的 Freezable 属性。
若要在 XAML 中以 Freezable 的属性为目标,请使用以下语法。
ElementPropertyName.FreezablePropertyName |
<ColorAnimation Storyboard.TargetProperty="(Fill).(Color)" To="LightBlue" Duration="0:0:5"></ColorAnimation>
有时,需要以集合或数组中包含的 Freezable 为目标。
若要以集合中包含的 Freezable 为目标,可以使用以下路径语法。
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName |
其中 CollectionIndex 是对象在对象数组或集合中的索引。
矩形具有应用于其 RenderTransform 属性的 TransformGroup 资源,您希望对它包含的变换之一进行动画处理。
这里的UIElement.RenderTransform其实也就是Rectangle.RenderTransform,(TransformGroup.Children)[1].(RotateTransform.Angle)或者是(TransformGroup.Children)[1].Angle就是真正动画作用的属性。其中的(TransformGroup.Children)也就是RenderTransform.Children,所以TargetProperty写法也可以是,(RenderTransform).Children[1].Angle。
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Storyboard.TargetName="myRec"
Storyboard.TargetProperty=" (UIElement.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
From="0" To="360" Duration="0:0:3" RepeatBehavior="Forever">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Grid.Triggers>
也可以是这样子(WPF测试有效):
(Rectangle.RenderTransform).(RotateTransform.Angle)
在后置代码中设置间接目标:
下面这个例子是在后台代码中设置简单的附加属性和设置间接的目标(单个元素,没有涉及的集合),在此需要主要设置附加属性时候必须在属性外加上(),例子中的是
(Canvas.Left),间接属性的设置这个()要与否,关键在判断要设置的属性是不是另一个对象的属性,在例子中要设置Fill属性,可是Fill的类型是Brush(在例子中给Ellipse
设置的是SolidColorBrush),而SolidColorBrush的Color类型才是要设置的真正属性,由于Fill类型的值是Bursh类型,所以需要写成(Fill)表示一个Brush(SolidColorBrush)
,所以最终的类型是(Fill).Color
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.DarkGray;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 200;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
//定义一个Brush
SolidColorBrush myBackgroundBrush = new SolidColorBrush();
myBackgroundBrush.Color = Colors.Blue;
//将当前的元素(myEllipse为一个Ellipse元素)的Fill赋值为定义的Brush
myEllipse.Fill = myBackgroundBrush;
//设置动画的Target和Property
Storyboard.SetTarget(myDoubleAnimation, myEllipse);
//修改附加属性,需要
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath("(Canvas.Left)", new object[0]));
//设置动画的Target和Property
//修改间接属性
Storyboard.SetTarget(myColorAnimation, myEllipse);
//指定的属性是Fill.Color而不是Fill
Storyboard.SetTargetProperty(myColorAnimation, new PropertyPath("(Fill).Color"));
//这种做法和上一种效果等同
//修改的是间接属性,即Fill属性,只能修改Ellipse的Fill属性对应的Brush,而不是直接修改Ellipse
Storyboard.SetTarget(myColorAnimation, myBackgroundBrush);
//修改的的属性是Brush的Color属性
Storyboard.SetTargetProperty(myColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
myStoryboard.Children.Add(myDoubleAnimation);
myStoryboard.Begin();
复杂的间接属性设置(集合类型),这个相比上个设置更为复杂了,因为设置的属性是在一个组中的,所以有集合这个概念,不过没关系,还是一层一层的去找
(UIElement.RenderTransform)或者(RenderTransform)表示当前元素的RenderTransform属性,Children表示RenderTransform的TransformGroup,Children[0]表示第一个RenderTransform也就是RotateTransform ,Angel表示RotateTransfo的Angel属性:
前台代码:
<Ellipse Fill="Red" Height="100" Width="100" Canvas.Top="100" x:Name="myEllipse">
<Ellipse.RenderTransform>
<TransformGroup>
<RotateTransform ></RotateTransform>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
后台代码:
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 90;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
//设置动画的Target和Property
Storyboard.SetTarget(myDoubleAnimation, myEllipse);
//修改附加属性
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath("(RenderTransform).Children[0].Angle", new object[0]));
Storyboard sb = new Storyboard();
sb.Children.Add(myDoubleAnimation);
sb.Begin();
重大消息,必须注意,本人在制作动画中发现一个严重问题,在设置Target和TargetProperty时候,MS提供了两种方式,一种是使用Animation的SetValue方法传递参数为
(StoryBoard.TargetNameProperty,"ElementName")和(StoryBoard.TargetPropertyProerty,new PropertyPath("PropertyName")),但是笔者发现,这种方式怎么着
都是有异常的,至今得不到答案(通过查看资料发现,此方法应该是在WPF中使用的,并且使用的"ElementName"必须是使用this.RegisterName("ElementName",element)来注册的,但是在Silverlight中是没有这个方法的,实在郁闷).好了不管这个bug了,看看常规的额使用方法:
那就是使用 StoryBoard.SetTarget方法和StoryBoard.SetTargetProperty方法前者用来设置目标对象,第一个参数为Animation,第二个为要设置的元素(Element,也就是控件对象).后者方法是设置属性,第一个参数还是Animation,第二个参数是PropertyPath也就是要设置的属性,在此要注意参数的写法,在上边有介绍。