Charles Petzold escribió una biblioteca para hacer esto en WPF. La lógica, al menos, debería ser transferible a Silverlight. Utiliza Polylines y Paths y debería ser fácil de portar.
Lines with Arrows @ Petzold Book Blog
--EDIT--
Ok - aquí hay otra manera de hacerlo:
Crear un control de usuario:
<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>
con la siguiente código:
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);
}
}
}
llamada así:
LayoutRoot.Children.Add(new ArrowsAndDaggersUC(new Point(200, 200), new Point(300, 400)));
y tendrá líneas de trazo 1px con triángulos de carrera 20 píxeles en el final de cada línea.
--EDIT--
@ Number8 tenía una pregunta acerca de cómo modificar el control de usuario de modo que las tapas se apuntan en la misma dirección que la línea.
Modificar el Xaml del control de usuario, así:
<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>
A continuación, cambiar el método de "Update" para obtener el ángulo de la línea y girar las tapas a ese ángulo:
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;
}
Ese es un código interesante, pero en Silverlight no puedo heredar de Line (o forma para el caso) como lo hizo Petzold en WPF.La línea está sellada y Shape no hace ningún dibujo. Creo que el tiempo de ejecución es el encargado de dibujar porque cada una de las clases de Shape tiene un "identificador conocido" diferente. –
El segundo ejemplo funcionó. Gracias. –
Buen trabajo. Parece que las flechas apuntan de este a oeste, incluso cuando la línea corre nw - se. ¿Qué se necesita para que las puntas de flecha apunten en la misma dirección en que se está ejecutando la línea? – Number8