views:

1136

answers:

2

I'm working on a project that involves drawing curved paths between two objects. Currently, I've been writing some test code to play around with bezier curves and animation. The first test is simply to move the endpoint (Point3) from the origin object (a rectangle) to the destination object (another rectangle), in a straight line. here is the code which sets up the actual line:

        connector = new Path();
        connector.Stroke = Brushes.Red;
        connector.StrokeThickness = 3;

        PathGeometry connectorGeometry = new PathGeometry();
        PathFigure connectorPoints = new PathFigure();
        connectorCurve = new BezierSegment();

        connectorPoints.StartPoint = new Point((double)_rect1.GetValue(Canvas.LeftProperty) + _rect1.Width / 2,
            (double)_rect1.GetValue(Canvas.TopProperty) + _rect1.Height / 2);
        connectorCurve.Point1 = connectorPoints.StartPoint;
        connectorCurve.Point2 = connectorPoints.StartPoint;
        connectorCurve.Point3 = connectorPoints.StartPoint;

        connectorPoints.Segments.Add(connectorCurve);
        connectorGeometry.Figures.Add(connectorPoints);
        connector.Data = connectorGeometry;
        MainCanvas.Children.Add(connector);

OK, so we now have a line collapsed to a point. Now, lets animate that line, going from _rect1 to _rect2 (the two objects at the endpoints):

        PointAnimation pointAnim = new PointAnimation();
        pointAnim.From = connectorCurve.Point3;
        pointAnim.To = new Point((double)_rect2.GetValue(Canvas.LeftProperty) + _rect2.Width / 2,
            (double)_rect2.GetValue(Canvas.TopProperty) + _rect2.Height / 2);
        pointAnim.Duration = new Duration(TimeSpan.FromSeconds(5));
        board.Children.Add(pointAnim);

Works beautifully. However, when I try to do it with a storyboard, I get nothing. Here's the storyboarded code:

        Storyboard board = new Storyboard();
        PointAnimation pointAnim = new PointAnimation();
        pointAnim.From = connectorCurve.Point3;
        pointAnim.To = new Point((double)_rect2.GetValue(Canvas.LeftProperty) + _rect2.Width / 2,
            (double)_rect2.GetValue(Canvas.TopProperty) + _rect2.Height / 2);
        pointAnim.Duration = new Duration(TimeSpan.FromSeconds(5));

        Storyboard.SetTarget(pointAnim, connectorCurve);
        Storyboard.SetTargetProperty(pointAnim, new PropertyPath(BezierSegment.Point3Property));
        board.Children.Add(pointAnim);
        board.Begin();

Nothing moves. I'm suspecting there is a problem with what I'm feeding SetTarget or SetTargetProperty, but can't seem to figure it out. Does anyone have experience with animating line / bezier points in WPF?

A: 

Hi, a few hints:

http://msdn.microsoft.com/en-us/library/system.windows.media.animation.storyboard(VS.95).aspx says:

Do not attempt to call Storyboard members (for example, Begin) within the constructor of the page. This will cause the animation to fail silently.

..in case you were doing that!

The sample on that page also sets the Duration property of the Storyboard object.

Finally a general tip, with these kinds of UI objects and weird XAML object graphs once you've got the basics working best to put it in a ResourceDictionary and use something like 'Resources["Name"] as Storyboard' to get it back later.

Hope that's helpful: looks like the missing Duration should do the trick.

edit: Looks like Duration is set to Automatic by default, I will see what else I can come up with, please bear with me.. :)

Kieren Johnstone
+1  A: 

I recreated your code, and this works:

Storyboard.SetTarget(pointAnim, connector);
Storyboard.SetTargetProperty(pointAnim, new PropertyPath("Data.Figures[0].Segments[0].Point3"));

That fixes it :) It seems that the target needs to be the control itself.

Going one step down, like this:

Storyboard.SetTarget(pointAnim, connectorGeometry);
Storyboard.SetTargetProperty(pointAnim, new PropertyPath("Figures[0].Segments[0].Point3"));

...gives the InvalidOperationException:

'[Unknown]' property value in the path 'Figures[0].Segments[0].Point3' points to immutable instance of 'System.Windows.Media.PathFigure'.

Kieren Johnstone