Charles Petzold wrote a library for doing this in WPF. The logic, at least, should be transferable to Silverlight. It uses Polylines and Paths and should be easy to port.
Lines with Arrows @ Petzold Book Blog
--EDIT--
Ok -- here's another way to go about it:
Create a user control:
<UserControl x:Class="ArrowsAndDaggersLibrary.ArrowsAndDaggersUC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas x:Name="LayoutRoot">
<Line x:Name="Cap" />
<Line x:Name="Connector" />
<Line x:Name="Foot" />
</Canvas>
</UserControl>
with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace ArrowsAndDaggersLibrary
{
public partial class ArrowsAndDaggersUC : UserControl
{
private Point startPoint;
public Point StartPoint
{
get { return startPoint; }
set
{
startPoint = value;
Update();
}
}
private Point endPoint;
public Point EndPoint
{
get { return endPoint; }
set {
endPoint = value;
Update();
}
}
public ArrowsAndDaggersUC()
{
InitializeComponent();
}
public ArrowsAndDaggersUC(Point StartPoint, Point EndPoint)
{
InitializeComponent();
startPoint = StartPoint;
endPoint = EndPoint;
Update();
}
private void Update()
{
//reconfig
Connector.X1 = startPoint.X;
Connector.Y1 = startPoint.Y;
Connector.X2 = endPoint.X;
Connector.Y2 = endPoint.Y;
Connector.StrokeThickness = 1;
Connector.Stroke = new SolidColorBrush(Colors.Black);
Cap.X1 = startPoint.X;
Cap.Y1 = startPoint.Y;
Cap.X2 = startPoint.X;
Cap.Y2 = startPoint.Y;
Cap.StrokeStartLineCap = PenLineCap.Triangle;
Cap.StrokeThickness = 20;
Cap.Stroke = new SolidColorBrush(Colors.Black);
Foot.X1 = endPoint.X;
Foot.Y1 = endPoint.Y;
Foot.X2 = endPoint.X;
Foot.Y2 = endPoint.Y;
Foot.StrokeEndLineCap = PenLineCap.Triangle;
Foot.StrokeThickness = 20;
Foot.Stroke = new SolidColorBrush(Colors.Black);
}
}
}
Call it like this:
LayoutRoot.Children.Add(new ArrowsAndDaggersUC(new Point(200, 200), new Point(300, 400)));
and you will have 1px stroke lines with 20px stroke triangles on the end of each line.
--EDIT--
@Number8 had a question about how to modify the user control so that the caps would point in the same direction as the line.
Modify the Xaml of the user control like so:
<UserControl x:Class="ArrowsAndDaggersLibrary.ArrowsAndDaggersUC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas x:Name="LayoutRoot">
<Line x:Name="Cap">
<Line.RenderTransform>
<RotateTransform x:Name="CapRotateTransform" />
</Line.RenderTransform>
</Line>
<Line x:Name="Connector" />
<Line x:Name="Foot">
<Line.RenderTransform>
<RotateTransform x:Name="FootRotateTransform" />
</Line.RenderTransform>
</Line>
</Canvas>
</UserControl>
Then, change the "Update" method to get the angle of the line and rotate the caps to that angle:
private void Update()
{
double angleOfLine = Math.Atan2((endPoint.Y - startPoint.Y), (endPoint.X - startPoint.X)) * 180 / Math.PI;
Connector.X1 = startPoint.X;
Connector.Y1 = startPoint.Y;
Connector.X2 = endPoint.X;
Connector.Y2 = endPoint.Y;
Connector.StrokeThickness = 1;
Connector.Stroke = new SolidColorBrush(Colors.Black);
Cap.X1 = startPoint.X;
Cap.Y1 = startPoint.Y;
Cap.X2 = startPoint.X;
Cap.Y2 = startPoint.Y;
Cap.StrokeStartLineCap = PenLineCap.Triangle;
Cap.StrokeThickness = 20;
Cap.Stroke = new SolidColorBrush(Colors.Black);
CapRotateTransform.Angle = angleOfLine;
CapRotateTransform.CenterX = startPoint.X;
CapRotateTransform.CenterY = startPoint.Y;
Foot.X1 = endPoint.X;
Foot.Y1 = endPoint.Y;
Foot.X2 = endPoint.X;
Foot.Y2 = endPoint.Y;
Foot.StrokeEndLineCap = PenLineCap.Triangle;
Foot.StrokeThickness = 20;
Foot.Stroke = new SolidColorBrush(Colors.Black);
FootRotateTransform.Angle = angleOfLine;
FootRotateTransform.CenterX = endPoint.X;
FootRotateTransform.CenterY = endPoint.Y;
}