我在Metro XAML应用程序中搞乱了一些故事板。我必须在代码中创建Storyboard
。我想将Storyboard.TargetProperty
设置为CompositeTransform.Rotation
似乎不可能......
XAML中的My Storyboard如下所示:
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="60"/
</DoubleAnimationUsingKeyFrames>
</Storyboard>
我想创造类似的东西
重要提示:我不是要重新创建这个确切的故事板。我在自定义ContentControl
的代码中,因此this
是Control
,并且没有“网格”来定位动画。目标是控件本身,其先前已设置CompositeTransform
。
到目前为止我的代码是这样的:
var turnSB = new Storyboard();
var doubleAnim = new DoubleAnimationUsingKeyFrames();
doubleAnim.KeyFrames.Add(new EasingDoubleKeyFrame() { KeyTime = TimeSpan.FromMilliseconds(0), Value = currentAngle });
doubleAnim.KeyFrames.Add(new EasingDoubleKeyFrame() { KeyTime = TimeSpan.FromMilliseconds(500), Value = targetAngle });
turnSB.Children.Add(doubleAnim);
Storyboard.SetTarget(doubleAnim, this.RenderTransform);
Storyboard.SetTargetProperty(doubleAnim, "(CompositeTransform.Rotation)");
turnSB.Begin();
一旦遇到Begin方法,我就会得到一个异常,说无法解析(CompositeTransform.Rotation)。所以我猜我没有完全正确的属性路径。我尝试了不同的变化,但根据PropertyPaths,这应该是正确的,不应该吗? :S
如果这是一个无法解决的问题,我愿意接受有关解决方法的建议......
修改
我想我现在已经解决了这个问题。我有一些有趣的发现......
如果我创建一个UserControl,我几乎可以做任何事情。一切正常,我可以设置Storyboard.Targetproperty,动画播放正确。
但是,如果我使用自定义控件,或从其他控件(比如ContentControl)继承,我无法从代码启动Storyboard,仅在某些情况下。
例如:如果我创建一个故事板(在XAML中定义)来为Rotation(或任何转换属性)设置动画并尝试从代码开始,我会得到上述异常。但是,如果我为一个简单的属性设置动画,比如Opacity,那就可以了。
(我使用UserControl做了同样的事情,但它确实有效。)
有人可以解释一下吗?
答案 0 :(得分:4)
从MSDN docs看起来你需要设置整个字符串路径。因此,对于xaml中描述的动画,您需要将TargetProperty设置为
Storyboard.SetTargetProperty(doubleAnim, "(UIElement.RenderTransform).(CompositeTransform.Rotation)");
<强>更新强>: 找到了这个blog post,它将时间轴添加为故事板的子项。请尝试以下方法:
Storyboard.SetTarget(doubleAnim, this.RenderTransform);
Storyboard.SetTargetProperty(doubleAnim, "Rotation"); // maybe "CompositeTransform.Rotation"
storyboard.Children.Add(doubleAnim);
答案 1 :(得分:4)
我认为您收到此错误的原因是您没有实例化自定义控件的RenderTransform
属性。
public class CustomControl2 : Control
{
public CustomControl2()
{
this.DefaultStyleKey = typeof(CustomControl2);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
public void RunAnimation()
{
//this.RenderTransform = new CompositeTransform();
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x33, 0xC8, 0x9C));
var turnSB = new Storyboard();
var doubleAnim = new DoubleAnimationUsingKeyFrames();
doubleAnim.KeyFrames.Add(new EasingDoubleKeyFrame() { KeyTime = TimeSpan.FromMilliseconds(0), Value = 10 });
doubleAnim.KeyFrames.Add(new EasingDoubleKeyFrame() { KeyTime = TimeSpan.FromMilliseconds(500), Value = 30 });
turnSB.Children.Add(doubleAnim);
Storyboard.SetTarget(doubleAnim, this.RenderTransform);
Storyboard.SetTargetProperty(doubleAnim, "(CompositeTransform.Rotation)");
turnSB.Begin();
}
}
请注意,在上面的代码中,如果我在方法RunAnimation
下注释掉第一行,它会给我带来同样的错误。
然后我在主页面中创建了这个控件,并创建了一个Button
来启动动画。
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.MyControl.RunAnimation();
}
我测试了上面的代码并且工作正常。
答案 2 :(得分:1)
解决了它
问题在于你使用的元素的路径,它必须从父类派生它扩展到属性本身。我让它在我自己的控制下工作,所以做了一个小例子,你可以复制粘贴(UNTESTED CODE):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
namespace CustomControls
{
/// <summary>
/// Author: Frank Wolferink
/// Note: example is untested and comes as is. I hope it save's you the time i lost figering this out
/// </summary>
public class CustomControl : Control
{
private Storyboard _compositeTransformExampleStoryBoard;
private const string TRANSLATE_X_TARGET = "Control.RenderTransform.CompositeTransform.TranslateX";
private const string TRANSLATE_Y_TARGET = "Control.RenderTransform.CompositeTransform.TranslateY";
private const string TRANSLATE_ROTATE_TARGET = "Control.RenderTransform.CompositeTransform.Rotation";
public CustomControl()
{
this.RenderTransform = new CompositeTransform();
TimeSpan duration = new TimeSpan(0,0,0,0,500);
double translateX = 10;
double translateY = 10;
double rotation = 40;
_compositeTransformExampleStoryBoard = BuildStoryboard(duration, translateX, translateY, rotation);
this.Loaded += CustomControl_Loaded;
}
void CustomControl_Loaded(object sender, RoutedEventArgs e)
{
_compositeTransformExampleStoryBoard.Begin();
}
private Storyboard BuildStoryboard(TimeSpan animationDuration, double transistionValueX, double transistionValueY, double rotation)
{
Storyboard storyboard = new Storyboard();
if (transistionValueX != 0)
CreateAnimation(storyboard, transistionValueX, animationDuration, TRANSLATE_X_TARGET);
if (transistionValueY != 0)
CreateAnimation(storyboard, transistionValueY, animationDuration, TRANSLATE_Y_TARGET);
if (rotation != 0)
CreateAnimation(storyboard, rotation, animationDuration, TRANSLATE_ROTATE_TARGET);
return storyboard;
}
private void CreateAnimation(Storyboard storyboard, double transistionValue, TimeSpan animationDuration, string targetProperty)
{
DoubleAnimation da = CreateDoubleAnimation(transistionValue, animationDuration);
storyboard.Children.Add(da);
Storyboard.SetTarget(da, this);
Storyboard.SetTargetProperty(da, targetProperty);
}
private DoubleAnimation CreateDoubleAnimation(double transistionValue, TimeSpan duration)
{
return new DoubleAnimation()
{
Duration = duration,
To = transistionValue
};
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
namespace CustomControls
{
/// <summary>
/// Author: Frank Wolferink
/// Note: example is untested and comes as is. I hope it save's you the time i lost figering this out
/// </summary>
public class CustomControl : Control
{
private Storyboard _compositeTransformExampleStoryBoard;
private const string TRANSLATE_X_TARGET = "Control.RenderTransform.CompositeTransform.TranslateX";
private const string TRANSLATE_Y_TARGET = "Control.RenderTransform.CompositeTransform.TranslateY";
private const string TRANSLATE_ROTATE_TARGET = "Control.RenderTransform.CompositeTransform.Rotation";
public CustomControl()
{
this.RenderTransform = new CompositeTransform();
TimeSpan duration = new TimeSpan(0,0,0,0,500);
double translateX = 10;
double translateY = 10;
double rotation = 40;
_compositeTransformExampleStoryBoard = BuildStoryboard(duration, translateX, translateY, rotation);
this.Loaded += CustomControl_Loaded;
}
void CustomControl_Loaded(object sender, RoutedEventArgs e)
{
_compositeTransformExampleStoryBoard.Begin();
}
private Storyboard BuildStoryboard(TimeSpan animationDuration, double transistionValueX, double transistionValueY, double rotation)
{
Storyboard storyboard = new Storyboard();
if (transistionValueX != 0)
CreateAnimation(storyboard, transistionValueX, animationDuration, TRANSLATE_X_TARGET);
if (transistionValueY != 0)
CreateAnimation(storyboard, transistionValueY, animationDuration, TRANSLATE_Y_TARGET);
if (rotation != 0)
CreateAnimation(storyboard, rotation, animationDuration, TRANSLATE_ROTATE_TARGET);
return storyboard;
}
private void CreateAnimation(Storyboard storyboard, double transistionValue, TimeSpan animationDuration, string targetProperty)
{
DoubleAnimation da = CreateDoubleAnimation(transistionValue, animationDuration);
storyboard.Children.Add(da);
Storyboard.SetTarget(da, this);
Storyboard.SetTargetProperty(da, targetProperty);
}
private DoubleAnimation CreateDoubleAnimation(double transistionValue, TimeSpan duration)
{
return new DoubleAnimation()
{
Duration = duration,
To = transistionValue
};
}
}
}