【问题标题】:Can't set Storyboard.TargetProperty to CompositeTransform.Rotation in Metro style app from code无法通过代码在 Metro 风格应用程序中将 Storyboard.TargetProperty 设置为 CompositeTransform.Rotation
【发布时间】:2012-08-09 04:36:02
【问题描述】:

我在 Metro XAML 应用程序中弄乱了一些情节提要。我必须在代码中创建一个Storyboard。我想将Storyboard.TargetProperty 设置为CompositeTransform.Rotation

似乎不可能……

我在 XAML 中的故事板如下所示:

<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 的代码中,所以thisControl,并且没有将动画定位到的“网格”。目标是控件本身,它之前设置了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.Target 属性,并且动画可以正确播放。

但是,如果我使用自定义控件,或从另一个控件(例如 ContentControl)继承,我无法从代码中启动 Storyboard,只有在某些情况下。

例如:如果我制作一个故事板(在 XAML 中定义)来动画旋转(或任何与此相关的转换属性)并尝试从代码开始,我会得到上述异常。但是如果我为一个简单的属性设置动画,比如不透明度,它就可以正常工作。
(我对 UserControl 做了同样的事情,并且它有效。)

有人可以解释一下吗?

【问题讨论】:

  • 我遇到了同样的问题,继承了 Grid 控件的类,故事板根本无法启动。
  • 需要注意的一点是 Grid 不是从 Control 继承的,所以它并不是你真正创建的自定义控件。
  • 我没有使用 Grid,我是从 ContentControl 继承的。 xaml 来自先前的尝试,其中我有一个 UserControl,其中有一个 Grid,这是动画的目标。但是对于这种情况,目标应该是控件本身。其中 - 如果您仔细阅读 - 我在“重要”部分中进行了描述。
  • Tenshiko,抱歉我指的是@sharpjohnny 的评论...

标签: storyboard microsoft-metro winrt-xaml attached-properties


【解决方案1】:

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);

【讨论】:

  • 我已经尝试了所有这些组合。结果总是一样的。
  • 我得出的结论是,问题不在于情节提要设置。实际上,您的第一个建议现在有效,但仅适用于 UserControls。我想了解更多有关该主题的信息,也许有人可以对此有所了解。但如果不是,我会接受你的回答。谢谢 :)
  • 所以这是在自定义控件中?
  • 其实我先做了一个继承自ContentControl的控件。它没有用。然后我将其更改为自定义控件。也没有用。现在我正在使用 UserControl,它可以工作。
【解决方案2】:

我认为您收到此错误的原因是因为您没有实例化自定义控件的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();
}

我测试了上面的代码,它运行良好。

【讨论】:

  • 我明白为什么这应该有效,但正如我在原始帖子中所说,我确实设置了转换(请再次阅读“重要”部分)。更重要的是,我能够用更简单的解决方案重现相同的效果。让我再检查一遍,然后再回复你。
  • 我能想到的一件事是,也许你在调用OnApplyTemplate 之前就开始动画了?
【解决方案3】:

解决了

问题出在您使用的元素的路径中,它必须从父类派生到属性本身。我让它在我自己的控制下工作,所以做了一个小例子,你可以复制粘贴(未经测试的代码):

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
            };
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多