WPF如何在2个组件之间绘制箭头

WPF how to draw an arrow between 2 component

我为我的程序创建了一个自定义树(由于各种原因不能使用树视图),但不清楚哪个组件是哪个孩子的 parent。我想添加可以这样调用的箭头:

var arrow = CreateArrowBetween(c1,c2)

但我不知道怎么做,有人可以帮助我或给我一个线索吗? Ps :现在元素在网格上

以下示例展示了如何在容器中托管的两个 FrameworkElement 元素之间绘制居中箭头,例如 Grid.

它非常基础,需要改进才能检测元素是否堆叠或彼此相邻。现在,该算法假定堆叠元素并将箭头水平居中放置在元素的 bottom/top 边缘上。
如果元素彼此相邻,您可能需要连接 left/right 边。 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);
  }
}