Mike Hodnick's Blog

Connectable lines and shapes in Silverlight

This is strictly just a UI concept at this point, but it's a very simple Silverlight implementation of drawing some shapes on the screen, connecting them with lines, then clicking and dragging the shapes around while maintaining the line connections.

UPDATE 1/6/2009: The demo page and source code have been updated and compiled for Silverlight 2.

Source Code: nodeconnect2.zip [12 kb]

Example App: http://kindohm.com/sl/NodeConnect/TestPage.html

movablenodes

It's hard to explain the highlights with only small code snippets (I don't want to paste the entire source code into this post), but here is a shot at some of the key features...

The nodes/shapes were implemented as Silverlight user controls. Clicking and dragging was simply handled on the user control's MouseMove event in combination with up/down state of the left mouse button. The MoveNode method does the dirty work:

Point lastPoint;

//declared as a XAML element...
TranslateTransform translation;

void MoveNode(Point currentPosition)
{
double deltaX = currentPosition.X - this.lastPoint.X;
double deltaY = currentPosition.Y - this.lastPoint.Y;
this.translation.X = this.translation.X + deltaX;
this.translation.Y = this.translation.Y + deltaY;
this.lastPoint = position;
}

As for drawing and re-drawing the lines, I created a Connection class that is just a data structure that describes a Line and where it starts from. To update the lines when a shape is moved, I just iterate through a Dictionary that stores a Connection for each control that the moved control is connected to. The Dictionary is maintained for all controls so that each control is aware of everything it is connected to:

public class NodeControl
{

...

void MoveConnections()
{
foreach (NodeControl key in this.connections.Keys)
{
Connection connection = this.connections[key];
Point newPosition =
NodeControl.GetCoordinatesForControl(this);
Line line = connection.Line;

//IsPrimary determines if this
//control holds the start or end
//of the line
if (connection.IsPrimary)
{
line.X1 = newPosition.X;
line.Y1 = newPosition.Y;
}
else
{
line.X2 = newPosition.X;
line.Y2 = newPosition.Y;
}
}
}

...

}

Oh the data visualization possibilities...

Enjoy.

Technorati Tags: