1

The following code effectively creates and animates a single rectangle. What I would like to be able to do is create and animate multiple rectangles.

I get an error as soon as I change qtyX and qtyYto more than one.

Any idea how can I solve this issue?

Cannot register duplicate name 'MyAnimatedRectangleGeometry' in this scope.

XAML:

<Canvas Name="MyCanvas" Background="#FFFFF5F5"/>

Codebehind:

private void button_Click(object sender, RoutedEventArgs e)
    {
        double length = 100;
        double height = 50;

        int qtyX = 1;
        int qtyY = 2;

        for (int i = 0; i < qtyX; i++) {
            for (int j = 0; j < qtyY; j++) {
                RectangleGeometry myRectangleGeometry = new RectangleGeometry();
                myRectangleGeometry.Rect = new Rect(((length + 1) * i), ((height + 1) * j), length, height);
                this.RegisterName(
                    "MyAnimatedRectangleGeometry", myRectangleGeometry);

                Path myPath = new Path();
                myPath.Fill = Brushes.Blue;
                myPath.Data = myRectangleGeometry;

                RectAnimation myRectAnimation = new RectAnimation();
                myRectAnimation.Duration = TimeSpan.FromSeconds(0.5);
                myRectAnimation.FillBehavior = FillBehavior.HoldEnd;

                myRectAnimation.From = new Rect(((length + 1) * i), ((height + 1) * j), length /2, height/2);

                Storyboard.SetTargetName(myRectAnimation, "MyAnimatedRectangleGeometry");
                Storyboard.SetTargetProperty(
                    myRectAnimation, new PropertyPath(RectangleGeometry.RectProperty));

                Storyboard ellipseStoryboard = new Storyboard();
                ellipseStoryboard.Children.Add(myRectAnimation);


                myPath.Loaded += delegate (object s, RoutedEventArgs r) {
                    ellipseStoryboard.Begin(this);
                };
                MyCanvas.Children.Add(myPath);
            }
        }
    }

FYI - I need to use RectangleGeometry.Rect for performance purposes.

fs_tigre
  • 10,650
  • 13
  • 73
  • 146

2 Answers2

1

You don't need a Storyboard. Just apply the animation directly to the RectangleGeometry:

myRectangleGeometry.BeginAnimation(RectangleGeometry.RectProperty, myRectAnimation);

The complete inner loop body:

var myRectangleGeometry = new RectangleGeometry(
    new Rect(((length + 1) * i), ((height + 1) * j), length, height));

var myPath = new Path
{
    Fill = Brushes.Blue,
    Data = myRectangleGeometry
};

var myRectAnimation = new RectAnimation
{
    Duration = TimeSpan.FromSeconds(0.5),
    From = new Rect(((length + 1) * i), ((height + 1) * j), length / 2, height / 2)
};

myRectangleGeometry.BeginAnimation(RectangleGeometry.RectProperty, myRectAnimation);

MyCanvas.Children.Add(myPath);

For completeness, to make it work with a Storyboard, use Target instead of TargetName:

Storyboard.SetTarget(myRectAnimation, myRectangleGeometry);
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • This is exactly what I needed, I do not need to use storyboards. Thanks! – fs_tigre Jul 17 '18 at 18:45
  • @ Clemens - Hmm, interesting how you restructured my code, are there any advantages by grouping it as you did? – fs_tigre Jul 17 '18 at 18:50
  • @ Clemens - One last question, why is `myPath.Loaded += (s, r) =>...` needed? – fs_tigre Jul 17 '18 at 18:55
  • 1
    It's a [lambda expression instead of an anonymous delegate](https://stackoverflow.com/q/299703/1136211), also just shorter. – Clemens Jul 17 '18 at 18:57
  • 1
    Well, my point is that I removed that completely from my code along with the storyboards and it works just fine. – fs_tigre Jul 17 '18 at 19:04
1

You need to provide a unique name for each geometry ...

this.RegisterName(
                "MyAnimatedRectangleGeometry" + someUniqueValue, myRectangleGeometry);

Where someUniqueValue is a variable that takes a new value on each iteration of your inner loop.