views:

493

answers:

1

I am playing around with some stuff in Silverlight, and I am trying to dynamically draw a curved line between two other objects on a <Canvas/>. I tried doing something like this:

public partial class MainNodeConnection : UserControl
    {
        private MainNode _sourceNode;
        public MainNode SourceNode 
        {
            get { return _sourceNode; }
            set { _sourceNode = value; }
        }

        private ChildNode _targetNode;
        public ChildNode TargetNode 
        {
            get { return _targetNode; }
            set { _targetNode = value; }
        }

        private double _sourceX;
        private double _sourceY;
        private double _targetX;
        private double _targetY;

        private Path _connection;

        public MainNodeConnection()
        {
            InitializeComponent();
            _connection = new Path();
            this.Content = _connection;
        }

        public void UpdateLocations()
        {
            _sourceX = Canvas.GetLeft(_sourceNode) + (SourceNode.Width/2);
            _sourceY = Canvas.GetTop(_sourceNode) + (SourceNode.Height/2);
            _targetX = Canvas.GetLeft(_targetNode);
            _targetY = Canvas.GetTop(_targetNode);
            string pathData = String.Format("M {0},{1} C {2},{3} {4},{5}", _sourceX, _sourceY, _targetX - _sourceX, _targetY - _sourceX, _targetX, _targetY);
            PathGeometry geoData = new PathGeometry();
            PathFigure pFigure = new PathFigure();
            pFigure.StartPoint = new Point(_sourceX, _sourceY);
            BezierSegment pseg = new BezierSegment();
            pseg.Point1 = new Point(_targetX - _sourceX, _targetY - _sourceY);
            pFigure.Segments.Add(pseg);
            geoData.Figures.Add(pFigure);
            _connection.Stroke = new SolidColorBrush(Colors.Black);
            _connection.StrokeThickness = 1;
            _connection.Data = geoData;
            this.Content = _connection;
        }
    }

and I built the objects on the <Canvas/> like this:

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            MainNodeConnection mnc = new MainNodeConnection();
            mnc.Width = 300;
            mnc.Height = 300;
            Canvas.SetLeft(mnc, Canvas.GetLeft(mainNode1));
            Canvas.SetTop(mnc, Canvas.GetTop(mainNode1));
            mnc.SourceNode = mainNode1;
            mnc.TargetNode = childNode1;
            nodeCanvas.Children.Add(mnc);
            mnc.UpdateLocations();
        }
    }

the problem I have is I can't get the line to show up. Can anyone spot what I'm doing wrong, or is there a different/better way to do this?

+2  A: 

You're missing Point2 and Point3 in the Bezier curve. From the help file:

A cubic Bezier curve is defined by four points: a start point, an end point (Point3), and two control points (Point1 and Point2). The BezierSegment class does not contain a property for the starting point of the curve; it only defines the end point. The beginning point of the curve is the current point of the PathFigure to which the BezierSegment is added.

The two control points of a cubic Bezier curve behave like magnets, attracting portions of what would otherwise be a straight line toward themselves and producing a curve. The first control point, Point1, affects the beginning portion of the curve; the second control point, Point2, affects the ending portion of the curve. Note that the curve doesn't necessarily pass through either of the control points; each control point moves its portion of the line toward itself, but not through itself.

Otaku
is there a type of curve that only needs one control point?
Jason Miesionczek
there isn't, at least not in SL. you could potentially try an `ArcSegment` though as that may be easier to just create the allusion of a curve without the points. you'll need a start, end and radius.
Otaku
its ok, i got it working now. wrote a method to generate intermediate points based on start and end points.
Jason Miesionczek
great stuff jason.
Otaku