如何使用依赖属性在两个 WPF 控件之间画一条线?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16776829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:52:43  来源:igfitidea点击:

How to draw a line between two WPF controls using dependency properties?

wpfcanvascontrolsdependency-properties

提问by Daniel Pe?alba

I need to draw a line connectingtwo WPF controls. I have defined a dependency propertyin my Nodeobjects so if the Node is moved the line still connect the objects.

我需要画一条连接两个 WPF 控件的线。我已经在我的对象中定义了一个依赖属性Node所以如果移动节点,线仍然连接对象。

I have the following example but I'm unable to get it working.

我有以下示例,但无法使其正常工作。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Node node1 = new Node(myCanvas) { Width = 50, Height = 50 };
        Node node2 = new Node(myCanvas) { Width = 50, Height = 50 };

        Canvas.SetLeft(node1, 0);
        Canvas.SetLeft(node2, 200);

        Canvas.SetTop(node1, 0);
        Canvas.SetTop(node2, 0);

        myCanvas.Children.Add(node1);
        myCanvas.Children.Add(node2);

        Connector conn = new Connector();
        conn.Source = node1.AnchorPoint;
        conn.Destination = node2.AnchorPoint;

        myCanvas.Children.Add(conn);
    }
}

class Node : Control
{
    public static readonly DependencyProperty AnchorPointProperty =
        DependencyProperty.Register(
            "AnchorPoint", typeof(Point), typeof(Node),
                new FrameworkPropertyMetadata(new Point(0, 0), 
                FrameworkPropertyMetadataOptions.AffectsMeasure));

    public Point AnchorPoint
    {
        get { return (Point)GetValue(AnchorPointProperty); }
        set { SetValue(AnchorPointProperty, value); }
    }

    private Canvas mCanvas;

    public Node(Canvas canvas)
    {
        mCanvas = canvas;
        this.LayoutUpdated += Node_LayoutUpdated;
    }

    void Node_LayoutUpdated(object sender, EventArgs e)
    {
        Size size = RenderSize;
        Point ofs = new Point(size.Width / 2, size.Height / 2);
        AnchorPoint = TransformToVisual(this.mCanvas).Transform(ofs);
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawEllipse(
            Brushes.Red,
            null,
            new Point(Width / 2, Height / 2), Width / 2, Height / 2);
    }
}

public sealed class Connector : UserControl
{
    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register(
            "Source", typeof(Point), typeof(Connector),
            new FrameworkPropertyMetadata(default(Point)));

    public Point Source {
        get { return (Point)this.GetValue(SourceProperty); }
        set { this.SetValue(SourceProperty, value); }
    }

    public static readonly DependencyProperty DestinationProperty =
        DependencyProperty.Register(
            "Destination", typeof(Point), typeof(Connector),
                new FrameworkPropertyMetadata(default(Point)));

    public Point Destination {
        get { return (Point)this.GetValue(DestinationProperty); }
        set { this.SetValue(DestinationProperty, value); }
    }

    public Connector()
    {
        LineSegment segment = new LineSegment(default(Point), true);
        PathFigure figure = new PathFigure(default(Point), new[] { segment }, false);
        PathGeometry geometry = new PathGeometry(new[] { figure });
        BindingBase sourceBinding = 
           new Binding { Source = this, Path = new PropertyPath(SourceProperty) };
        BindingBase destinationBinding = 
           new Binding { Source = this, Path = new PropertyPath(DestinationProperty) };
        BindingOperations.SetBinding(
            figure, PathFigure.StartPointProperty, sourceBinding);
        BindingOperations.SetBinding(
            segment, LineSegment.PointProperty, destinationBinding);
        Content = new Path
        {
            Data = geometry,
            StrokeThickness = 5,
            Stroke = Brushes.White,
            MinWidth = 1,
            MinHeight = 1
        };
    }
}

采纳答案by Sphinxxx

All you have to do to make your example work is to bindconn.Sourceand .Destinationto the nodes' AnchorPoints, or else the Connector just get the AnchorPoints' initial values (0,0), and doesn't listen for further changes:

所有你需要做的,让您的例子的工作是绑定conn.Source.Destination到节点的AnchorPoints,否则连接器刚刚得到的AnchorPoints'初始值(0,0),并且不监听进一步修改:

...

Connector conn = new Connector();
//conn.Source = node1.AnchorPoint;
conn.SetBinding(Connector.SourceProperty, 
                new Binding()
                {
                    Source = node1,
                    Path = new PropertyPath(Node.AnchorPointProperty)
                });
//conn.Destination = node2.AnchorPoint;
conn.SetBinding(Connector.DestinationProperty,
                new Binding()
                {
                    Source = node2,
                    Path = new PropertyPath(Node.AnchorPointProperty)
                });

myCanvas.Children.Add(conn);