1

I have the following method which works. I'd like to put it in a utility method that returns a Storyboard. Every attempt I have made at converting this to a Storyboard has failed, and I've spent a lot of time researching. I'm ready to give up unless someone comes to my rescue.

Here's the code I want to convert:

public override void Begin(FrameworkElement element, int duration)
{
    var transform = new ScaleTransform();
    element.LayoutTransform = transform;

    var animation = new DoubleAnimation
                        {
                            From = 1,
                            To = 0,
                            Duration = TimeSpan.FromMilliseconds(duration),
                            FillBehavior = FillBehavior.Stop,
                            EasingFunction = new QuinticEase { EasingMode = EasingMode.EaseIn }
                        };

    transform.BeginAnimation(ScaleTransform.ScaleXProperty, animation);
    transform.BeginAnimation(ScaleTransform.ScaleYProperty, animation);
}

So, instead of the two BeginAnimation() calls, I want to return a Storyboard so all I have to do is call storyboard.Begin(). I know this shouldn't be that hard to do, but I'm just not getting it.

Thanks.

EDIT: In response to H.B's suggestions, I tried the following code, which still does not work:

private static Storyboard CreateAnimationStoryboard(FrameworkElement element, int duration)
{
    var sb = new Storyboard();
    var scale = new ScaleTransform(1, 1);
    element.RenderTransform = scale;
    element.RegisterName("scale", scale);

    var animation = new DoubleAnimation
    {
        From = 1,
        To = 0,
        Duration = TimeSpan.FromMilliseconds(duration),
        FillBehavior = FillBehavior.Stop,
        EasingFunction = new QuinticEase { EasingMode = EasingMode.EaseIn }
    };
    sb.Children.Add(animation);

    Storyboard.SetTarget(animation, scale);
    Storyboard.SetTargetProperty(animation, new PropertyPath(ScaleTransform.ScaleXProperty));

    return sb;
}

I know I only animated the X axis - just want to get something to work first.

Dan Thomas
  • 23
  • 2
  • 6

2 Answers2

0

You'll need two animations and then set the attached Storyboard properties to animated the right property on the right object using SetTargetProperty and SetTargetName.

Due to how storyboards work you also need to set a namescope (NameScope.SetNameScope), register the name of the transform, and call StoryBoard.Begin with the containing element overload.

e.g.

NameScope.SetNameScope(element, new NameScope());

var transform = new ScaleTransform();
var transformName = "transform";
element.RegisterName(transformName, transform);
element.RenderTransform = transform;

var xAnimation = new DoubleAnimation(2, TimeSpan.FromSeconds(1));
var yAnimation = xAnimation.Clone();

var storyboard = new Storyboard()
{
    Children = { xAnimation, yAnimation }
};

Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(ScaleTransform.ScaleX)"));
Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(ScaleTransform.ScaleY)"));

Storyboard.SetTargetName(xAnimation, transformName);
Storyboard.SetTargetName(yAnimation, transformName);

storyboard.Begin(element);
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Yeah, I got that much. Perhaps the details of the complications you mentioned might be helpful? – Dan Thomas Jul 29 '12 at 18:52
  • @DanThomas: [This](http://stackoverflow.com/a/4567058/546730) sounds like the problem. – H.B. Jul 29 '12 at 18:59
  • Thanks, but that particular issue is for if you're creating a framework element in code, which I'm not doing. The framework element already exists via xaml, and I'm calling this method via an attached behavior. Any other ideas? :) – Dan Thomas Jul 29 '12 at 19:12
  • @DanThomas: You are animating the transform, that is what needs a name. Also XAML creation would probably not be enough, you would also need to set a `Name` in XAML, the point is that you *always* need to set the name anyway if you want somethig animated in XAML, otherwise you cannot reference it. – H.B. Jul 29 '12 at 19:14
  • @DanThomas: Almost, see my edited answer. (I didn't get it to work with `SetTarget`, no idea if that is any use in code) – H.B. Jul 29 '12 at 20:52
  • I appreciate your help with this, but it's time to give up. I got this error, using your code: InvalidOperationException: No applicable name scope exists to resolve the name 'transform'. I don't want to spend any more time on this for now. But thanks for your help!! – Dan Thomas Jul 29 '12 at 23:02
  • @DanThomas: That should not happen :( maybe you forgot one the key-points? Well, it's your call, i wouldn't use a storyboard in code anyway. – H.B. Jul 29 '12 at 23:29
0

I suggest using Expression Blend and start recording from there, it should create your storyboards in XAML. Rather than hard coding it with C# and trying to translate it 1 by 1 to storyboard thus it can be a prone error.

123 456 789 0
  • 10,565
  • 4
  • 43
  • 72
  • Thanks, but I need to do them in code. I've created a behavior that I attach to an element and bind to a ViewModel property which allows the ViewModel to trigger an animated visibility transition, with a callback to the ViewModel when it's done. I suppose it's possible to still create the animations in xaml, but since I need the callbacks when they're done, everything is just easier to do in code. – Dan Thomas Jul 30 '12 at 03:02