如何使用Line排列Thumbs以在WPF自定义Adorner中移动一行

时间:2013-07-10 10:53:10

标签: c# wpf line adorner

我正在使用WPF在绘图程序中为Adorner处理LineLine在代码隐藏中绘制,然后使用名为Adorner的自定义LineAdorner进行装饰。我设法使用Thumb作为Line的起点和终点。它适用于调整大小。我的问题是我无法移动(拖放)线,怎么做?

public class ResizingAdorner : Adorner
{
    // Resizing adorner uses Thumbs for visual elements.  
    // The Thumbs have built-in mouse input handling.
    //Thumb topLeft, topRight, bottomLeft, bottomRight;

    private Thumb startThumb;
    private Thumb endThumb;
    private Line selectedLine;
    private Point startPoint;
    private Point endPoint;

    // To store and manage the adorner's visual children.
    VisualCollection visualChildren;
    bool IsControlModeOn = false;
    // Override the VisualChildrenCount and GetVisualChild properties to interface with 
    // the adorner's visual collection.
    protected override int VisualChildrenCount { get { return visualChildren.Count; } }
    protected override Visual GetVisualChild(int index) { return visualChildren[index]; }

    // Initialize the ResizingAdorner.
    public ResizingAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
        visualChildren = new VisualCollection(this);
        selectedLine = AdornedElement as Line;
        startThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.Green };
        endThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.BlueViolet };
        startThumb.DragDelta += StartDragDelta;
        endThumb.DragDelta += EndDragDelta;

        startThumb.DragCompleted += new DragCompletedEventHandler(startThumb_DragCompleted);
        endThumb.DragCompleted += new DragCompletedEventHandler(endThumb_DragCompleted);

        visualChildren.Add(startThumb);
        visualChildren.Add(endThumb);
    }


    public event EndDragDeltaEvent endDragDeltaEvent;
    public delegate void EndDragDeltaEvent(object obj, DragCompletedEventArgs e, bool isEnd);

    void startThumb_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        if (endDragDeltaEvent != null)
            endDragDeltaEvent(selectedLine, e, false);
    }

    void endThumb_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        if (endDragDeltaEvent != null)
            endDragDeltaEvent(selectedLine, e, true);
    }

    // Arrange the Adorners.
    protected override Size ArrangeOverride(Size finalSize)
    {
        selectedLine = AdornedElement as Line;

        double left = Math.Min(selectedLine.X1, selectedLine.X2);
        double top = Math.Min(selectedLine.Y1, selectedLine.Y2);

        var startRect = new Rect(selectedLine.X1 - (startThumb.Width / 2), selectedLine.Y1 - (startThumb.Width / 2), startThumb.Width, startThumb.Height);
        startThumb.Arrange(startRect);

        var endRect = new Rect(selectedLine.X2 - (endThumb.Width / 2), selectedLine.Y2 - (endThumb.Height / 2), endThumb.Width, endThumb.Height);
        endThumb.Arrange(endRect);

        return finalSize;
    }

    private void StartDragDelta(object sender, DragDeltaEventArgs e)
    {
        Point position = Mouse.GetPosition(this);

        selectedLine.X1 = position.X;
        selectedLine.Y1 = position.Y;
    }

    // Event for the Thumb End Point
    private void EndDragDelta(object sender, DragDeltaEventArgs e)
    {
        Point position = Mouse.GetPosition(this);

        selectedLine.X2 = position.X;
        selectedLine.Y2 = position.Y;
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        if (AdornedElement is Line)
        {
            selectedLine = AdornedElement as Line;
            startPoint = new Point(selectedLine.X1, selectedLine.Y1);
            endPoint = new Point(selectedLine.X2, selectedLine.Y2);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你需要在线上处理MouseDown,MouseMove和MouseUp事件才能做到这一点:

在构造函数中为这些事件添加处理程序

selectedLine.MouseLeftButtonDown += SelectedLineOnMouseLeftButtonDown;
selectedLine.MouseMove += SelectedLineOnMouseMove;
selectedLine.MouseLeftButtonUp += SelectedLineOnMouseLeftButtonUp;

实现就像这样

private Point origin;

private void SelectedLineOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{
    e.Handled = true;

    Line line = (Line) sender;
    line.CaptureMouse();

    startPoint = new Point(line.X1, line.Y1);
    endPoint = new Point(line.X2, line.Y2);

    origin = e.GetPosition(line);

    base.OnMouseLeftButtonDown(e);
}

private void SelectedLineOnMouseMove(object sender, MouseEventArgs e) 
{
    base.OnMouseMove(e);
    Line line = (Line) sender;
    if (e.MouseDevice.LeftButton == MouseButtonState.Pressed) 
    {
        Point position = e.GetPosition(this);
        e.Handled = true;
        double horizontalDelta = position.X - origin.X;
        double verticalDelta = position.Y - origin.Y;

        line.X1 = startPoint.X + horizontalDelta;
        line.X2 = endPoint.X + horizontalDelta;
        line.Y1 = startPoint.Y + verticalDelta;
        line.Y2 = endPoint.Y + verticalDelta;

        InvalidateArrange();
    }
    else 
    {
        line.ReleaseMouseCapture();
    }
}

private void SelectedLineOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
{
    Line line = (Line) sender;
    line.ReleaseMouseCapture();
    e.Handled = true;

    base.OnMouseLeftButtonUp(e);
}

我还在StartDragDelta和EndDragDelta处理程序中添加了一些InvalidateArrange()调用,以确保在拖动时拇指移动。