RenderTransform Mouse.GetPosition

1.7k Views Asked by At

Ok,Better with some Corrections and APPLIED ONLY TO X COORDINATE: Given following Code:

    private Point MouseDownPosition;

     private void OnStartDrag(object sender, MouseButtonEventArgs e)
    {
        if (!this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.AddHandler(FrameworkElement.MouseMoveEvent, new MouseEventHandler(this.OnDrag));
            this.AssociatedObject.RenderTransform = new TranslateTransform();
            this.MouseDownPosition = Mouse.GetPosition(null);
            Mouse.Capture(this.AssociatedObject, CaptureMode.Element);
        }
    }
    private void OnDrag(object sender, MouseEventArgs e)
    {
        if (this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.AddHandler(FrameworkElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.OnStopDrag));
            TranslateTransform Translate = this.AssociatedObject.RenderTransform as TranslateTransform;
            Point CurrentPosition = Mouse.GetPosition(null); 
            Translate.X = CurrentPosition.X - this.MouseDownPosition.X;
        }
    }
    private void OnStopDrag(object sender, MouseButtonEventArgs e)
    {
        if (this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.ReleaseMouseCapture();
            this.AssociatedObject.RemoveHandler(FrameworkElement.MouseMoveEvent, new MouseEventHandler(this.OnDrag));
            this.AssociatedObject.RemoveHandler(FrameworkElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.OnStopDrag));
        }
    }

1.(MouseLeftButtonDown) When I click on the FIRST time on the Dragged Object,It is moving correctely.

2.(MouseMove)I drag the object in an arbitrary position ex. 100 points right on my Panel.

3.(MouseLeftButtonUp) The object is positioned correctely WHERE I LEFT IT DRAGGING.

Until now NO problems.But when I Start the Event chain for SECOND TIME:

1.(MouseLeftButtonDown)The dragged object is shifted Back of:

                         CurrentPointerPosition + FIRSTPosition

2. (MouseMove)Drag move is executed but the MousePointer is at CurrentPointerPosition + FIRSTPosition FROM the dragged object.

3.(MouseLeftButtonUp) executed correctely as in First Time(but it was obvious).

It seems that on MouseLeftButtonDown the MouseDownPosition and the position of the dragged object must be resetted...

Why? What I'm doing wrong? Thank You!

2

There are 2 best solutions below

1
On

Ok,after digging hours,I finally found the SOLUTION. I pray everyone really experienced in WPF/Silverlight to explain me (and others who had this problem) WHY exactely my code is working,because,sincerely,I cannot find a logical reason:

public class DragBehavior : Behavior<FrameworkElement>
{
    #region Constructors

    static DragBehavior()
    {
    }
    public DragBehavior()
    {
    }

    #endregion

    private Point MouseDownPosition;

    protected override void OnAttached()
    {
        this.AssociatedObject.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, new      MouseButtonEventHandler(this.OnStartDrag));
        this.AssociatedObject.RenderTransform = new TranslateTransform();
        this.AssociatedObject.UpdateLayout();
        base.OnAttached();
    }
    protected override void OnDetaching()
    {
        this.AssociatedObject.RenderTransform = null;
        this.AssociatedObject.RemoveHandler(FrameworkElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.OnStartDrag));
        base.OnDetaching();
    }

    private void OnStartDrag(object sender, MouseButtonEventArgs e)
    {
        if (!this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.AddHandler(FrameworkElement.MouseMoveEvent, new MouseEventHandler(this.OnDrag));
            this.MouseDownPosition = Mouse.GetPosition(this.AssociatedObject);

            Mouse.Capture(this.AssociatedObject, CaptureMode.SubTree);
        }
    }
    private void OnDrag(object sender, MouseEventArgs e)
    {
        if (this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.AddHandler(FrameworkElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.OnStopDrag));
            TranslateTransform Translate = this.AssociatedObject.RenderTransform as TranslateTransform;
            Translate.X = (Mouse.GetPosition(this.AssociatedObject.Parent as FrameworkElement).X - this.MouseDownPosition.X) / 3;
            Translate.Y = (Mouse.GetPosition(this.AssociatedObject.Parent as FrameworkElement).Y - this.MouseDownPosition.Y) / 3;

            Point Position = new Point(Translate.X,Translate.Y);
            Size Size = this.AssociatedObject.DesiredSize;
            Rect Bounds = new Rect(Position,Size);

            this.AssociatedObject.Arrange(this.AssociatedObject.RenderTransform.TransformBounds(Bounds));
        }
    }
    private void OnStopDrag(object sender, MouseButtonEventArgs e)
    {
        if (this.AssociatedObject.IsMouseCaptured)
        {
            this.AssociatedObject.ReleaseMouseCapture();
            this.AssociatedObject.RemoveHandler(FrameworkElement.MouseMoveEvent, new MouseEventHandler(this.OnDrag));
            this.AssociatedObject.RemoveHandler(FrameworkElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.OnStopDrag));
        }
    }

I hope this helps everyone had/Will have this strange problem,to solve or to go deeper in the WPF Layout process to find any possible bug/unknown defaults by MS. I guess I don't know yet enough this huge argument which is WPF Layout. For now,I only suppose there's some scalar value in the Matrix product between Identity and the Translation Matrixes,maybe influencing the change of Basis in the container layout process,but it is only an algebraic consideration,without any proof in the MS implementation. Please,to everyone,explain HOW we can use TranslateTransform correctely and without depending on the Panel owner. Thank Everyone so much! Waiting for replies,considerations,EXPLAINATIONS of my code.

0
On

Thanks to "TheKiller556" on MSDN I found finally the correct approach to the problem,according to Layout Changes,so making a REAL Universal and robust Drag Behavior.

The link which doesn't solve the problem of RenderTransforms,seems solving with Margin property ALSO(tested) on complex logic Panels:

http://social.msdn.microsoft.com/Forums/en/wpf/thread/eb3a912b-1046-4902-8c7a-bbc0566209c0

I hope,in a future,there will a DEEPER explanation in transforms problems anyway. Thanks To all! (I know I cannot vote myself,but if someone look deep in my post,I effectively found a solution,so,If is possible,I would like to know if I can have some points for that.) Thank You again!