2

I have a drag/drop behavior for my RichTextBox in Silverlight 4, but i'm having a small snapping problem.

I would like the user to be able to "grab" any border of the RichTextBox and drag/drop it. The RichTextBox should drag relative to where the user "grabbed" the RichTextBox. But instead, as soon as the user begins the drag, the RichTextBox "snaps" to the middle of the mouse position instead of its position staying relative to the mouse position.

So if I grab the bottom right corner, as in the following ...

https://skydrive.live.com/redir?resid=DCC93DD825EF3F43!658

it "snaps" to the middle of the mouse position on the start of the dragging, as in the following ...

https://skydrive.live.com/redir?resid=DCC93DD825EF3F43!659

Here's my dragging code. I'm assuming my math is wrong (in the MouseMove event) ???


public class CustomRichTextBox : RichTextBox
{
    private bool isDragging = false;

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);

        bool isDragAllowed = false;
        Point pt = e.GetPosition(this);

        if (pt.Y >= 0 && pt.Y <= this.BorderThickness.Top)
            // Allow dragging if the mouse is down on the top border
            isDragAllowed = true;
        else if (pt.Y >= (this.RenderSize.Height - this.BorderThickness.Bottom) && pt.Y <= this.RenderSize.Height)
            // Allow dragging if the mouse is down on the bottom border
            isDragAllowed = true;
        else if (pt.X >= 0 && pt.X <= this.BorderThickness.Left)
            // Allow dragging if the mouse is down on the left border
            isDragAllowed = true;
        else if (pt.X >= (this.RenderSize.Width - this.BorderThickness.Right) && pt.X <= this.RenderSize.Width)
            // Allow dragging if the mouse is down on the right border
            isDragAllowed = true;

        if (!isDragAllowed)
            return;

        this.CaptureMouse();
        isDragging = true;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        if (isDragging)
        {
            CustomRichTextBox elem = this;
            CompositeTransform ct = (CompositeTransform)elem.RenderTransform;
            UIElement parent = (UIElement)elem.Parent;

            ct.TranslateX = e.GetPosition(parent).X - (parent.RenderSize.Width / 2);
            ct.TranslateY = e.GetPosition(parent).Y - (parent.RenderSize.Height / 2);
        }
    }

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonUp(e);

        isDragging = false;
        this.ReleaseMouseCapture();
    }
}
4

1 に答える 1

1

ここに欠けているのは、ドラッグが開始された位置への参照ポイントです。マウス移動イベントでは、コントロールを現在の位置と元の位置の間のデルタではなく、マウスの現在の位置に変換しようとしています。

または、相対座標を使用して、マウス クリックの位置をコントロールに相対的に格納し、OnMove で現在の位置から差し引くことができます。これは、以下のサンプルで起こっていることです。

これは CompositeTransform がない WPF であることに注意してください。親の RenderSize を減算することは、私には間違いのように見えます。または、WPF と Silverlight の違いかもしれません。とにかく、これが解決に役立つことを願っています。

public class CustomRichTextBox : RichTextBox
{
    private bool isDragging = false;
    private Point draggingPoint;

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonDown(e);

        bool isDragAllowed = false;
        Point pt = e.GetPosition(this);

        if (pt.Y >= 0 && pt.Y <= this.BorderThickness.Top)
            // Allow dragging if the mouse is down on the top border
            isDragAllowed = true;
        else if (pt.Y >= (this.RenderSize.Height - this.BorderThickness.Bottom) && pt.Y <= this.RenderSize.Height)
            // Allow dragging if the mouse is down on the bottom border
            isDragAllowed = true;
        else if (pt.X >= 0 && pt.X <= this.BorderThickness.Left)
            // Allow dragging if the mouse is down on the left border
            isDragAllowed = true;
        else if (pt.X >= (this.RenderSize.Width - this.BorderThickness.Right) && pt.X <= this.RenderSize.Width)
            // Allow dragging if the mouse is down on the right border
            isDragAllowed = true;

        if (!isDragAllowed)
            return;

        draggingPoint = pt;

        this.CaptureMouse();
        isDragging = true;
    }

    protected override void OnPreviewMouseMove(MouseEventArgs e)
    {
        base.OnPreviewMouseMove(e);

        if (isDragging)
        {
            CustomRichTextBox elem = this;
            TransformGroup ct = new TransformGroup();
            UIElement parent = (UIElement)elem.Parent;

            TranslateTransform tr = new TranslateTransform(
                e.GetPosition(parent).X - elem.RenderSize.Width + this.BorderThickness.Left - draggingPoint.X,
                e.GetPosition(parent).Y - elem.RenderSize.Height + this.BorderThickness.Top - draggingPoint.Y);

            ct.Children.Add(tr);

            elem.RenderTransform = ct;
        }
    }

    protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonUp(e);

        isDragging = false;
        this.ReleaseMouseCapture();
    }
}
于 2012-11-01T12:13:16.830 に答える