В следующем примере показано, как нарисовать центрированную стрелку между двумя элементами FrameworkElement
, размещенными в контейнере, например, Grid
.
Это очень базовый c и его необходимо улучшить, чтобы обнаруживать если элементы уложены друг на друга или рядом. Прямо сейчас алгоритм предполагает, что элементы расположены в стопке, и позиционирует стрелку горизонтально по центру на нижнем / верхнем краях элементов.
Если элементы расположены рядом друг с другом, вы можете захотеть соединить левый / правый края. MainWindow.xaml
<Window>
<Grid x:Name="Container">
<TextBox x:Name="TextBox" Text="Some text" Height="20" />
<TextBlock x:Name="TextBlock" Margin="0,100,0,0" Text="More text" />
</Grid>
</Window>
MainWindow.xaml.cs
partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
CreateArrowBetween(this.TextBlock, this.TextBox, this.Container);
}
// The arrow will point from start to end
private void CreateArrowBetween(FrameworkElement startElement, FrameworkElement endElemend, Panel parentContainer)
{
SolidColorBrush arrowBrush = Brushes.Red;
// Center the line horizontally and vertically.
// Get the positions of the controls that should be connected by a line.
Point centeredArrowStartPosition = startElement.TransformToAncestor(parentContainer)
.Transform(new Point(startElement.ActualWidth / 2, startElement.ActualHeight / 2));
Point centeredArrowEndPosition = endElemend.TransformToAncestor(parentContainer)
.Transform(new Point(endElemend.ActualWidth / 2, endElemend.ActualHeight / 2));
// Draw the line between two controls
var arrowLine = new Line()
{
Stroke = Brushes.Red,
StrokeThickness = 2,
X1 = centeredArrowStartPosition.X,
Y2 = centeredArrowEndPosition.Y,
X2 = centeredArrowEndPosition.X,
Y1 = centeredArrowStartPosition.Y
};
parentContainer.Children.Add(
arrowLine);
// Create the arrow tip of the line. The arrow has a width of 8px and a height of 8px,
// where the position of arrow tip and the line's end are the same
var arrowLineTip = new Polygon() {Fill = Brushes.Red};
var leftRectanglePoint = new Point(centeredArrowEndPosition.X - 4, centeredArrowEndPosition.Y + 8);
var rightRectanglePoint = new Point(
centeredArrowEndPosition.X + 4,
centeredArrowEndPosition.Y + 8);
var rectangleTipPoint = new Point(centeredArrowEndPosition.X, centeredArrowEndPosition.Y);
var myPointCollection = new PointCollection
{
leftRectanglePoint,
rightRectanglePoint,
rectangleTipPoint
};
arrowLineTip.Points = myPointCollection;
parentContainer.Children.Add(
arrowLineTip);
}
}