Search code examples
wpfdrag-and-dropwpf-controlsdraggablemousemove

WFP TranslateTransform Error


I am working on a drawing project. In which I have t create a draggable window where a user can Click on any Object and move it to different positions like we do in PhotoShop with our layers.

Programme I write is working perfectly for the One object on the screen and I can move to any position I want by simply dragging it. But when the number of objects is increased then it is causing a very weird problem. When I click on the any of the objects it creates a cluster of the all the objects on the windows and starts applying the transformation to the whole cluster.

Note : All the object are the Images and Container is Canvas.

Here are some images and code I am using.

    private Point _currentPoint;
    private Point _ancherPoint;
    private bool _isInDrag = false;
    private TranslateTransform _transform = new TranslateTransform();
    private Image _element;
    private void DropList_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )
    {
        _element = FindAnchestor<Image>( ( DependencyObject )e.OriginalSource );

        if( _element != null )
        {
            _ancherPoint = e.GetPosition( DropList );
            _isInDrag = true;
            _element.CaptureMouse();
            e.Handled = true;

        }
    }

    private void DropList_MouseMove( object sender, MouseEventArgs e )
    {
        if( _isInDrag )
        {
            _currentPoint = e.GetPosition( DropList );


            _transform.X += ( _currentPoint.X - _ancherPoint.X );
            _transform.Y += ( _currentPoint.Y - _ancherPoint.Y );

            Lbl.Content = _element.Source.ToString();

             Source on which transfrom is going to happen
            _element.RenderTransform = _transform;
            _ancherPoint = _currentPoint;
        }
    }
    private void DropList_MouseLeftButtonUp( object sender, MouseButtonEventArgs e )
    {
        if( _isInDrag )
        {
            _element.ReleaseMouseCapture();
            _isInDrag = false;
            e.Handled = true;
        }
    }

    private static T FindAnchestor<T>( DependencyObject current ) where T : DependencyObject
    {
        do
        {
            if( current is T )
            {
                return ( T )current;
            }
            current = VisualTreeHelper.GetParent( current );
        }
        while( current != null );
        return null;
    }

This is the single object I can move it to any place I want easily without any mess up. enter image description here

Here I have three objects. when I click any of them they make a cluster and start moving together. enter image description here


Solution

  • The problem is that you are using the same TranslateTransform instance for all elements. You should instead create a new instance for each element, either when you create the element, or e.g. in the MouseDown handler:

    private void DropList_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _element = FindAnchestor<Image>((DependencyObject)e.OriginalSource);
    
        if (_element != null)
        {
            var point = e.GetPosition((IInputElement)sender);
            _isInDrag = true;
            _element.CaptureMouse();
            _element.RenderTransform = new TranslateTransform(point.X, point.Y); // here
            e.Handled = true;
        }
    }
    

    And use it when moving:

    private void DropList_MouseMove(object sender, MouseEventArgs e)
    {
        if (_isInDrag)
        {
            var point = e.GetPosition((IInputElement)sender);
            var transform = (TranslateTransform)_element.RenderTransform;
            transform.X = point.X;
            transform.Y = point.Y;
        }
    }