0

On a wpf I have implemented the practice proposed as answer to the question: How to drag a UserControl inside a Canvas in order to drag and move items (shapes, child canvas) on a canvas. However as correctly indicated the next answer of the same question there is a flaw inside the method:

private void Control_MouseMove(object sender, MouseEventArgs e)
{
    var draggableControl = sender as UserControl;

    if (isDragging && draggableControl != null)
    {
        Point currentPosition = e.GetPosition(this.Parent as UIElement);

        var transform = draggableControl.RenderTransform as TranslateTransform;
        if (transform == null)
        {
            transform = new TranslateTransform();
            draggableControl.RenderTransform = transform;
        }

        transform.X = currentPosition.X - clickPosition.X;
        transform.Y = currentPosition.Y - clickPosition.Y;
    }
}

It uses the RenderTranform which does not changes the position of an item permanently but its visual position instead. The result is that the item returns to its initial position just on the next mouse event, so the drag and drop does not work properly (you cannot move it actually in this way but only visually).What kind of modification should be done on it to rectify the functionality of the method? Is there alternatively a similar practice that carries out the task properly? Should I use another Transform like Layout Transform?

Community
  • 1
  • 1
arjacsoh
  • 8,932
  • 28
  • 106
  • 166
  • The fact that the control's position is reset has nothing to do with the use of the RenderTransform, if anything it's just bad coding. – H.B. Nov 04 '11 at 11:01
  • Look at the remarks in http://msdn.microsoft.com/en-us/library/system.windows.uielement.rendertransform.aspx. It speaks about a "temporary effect". – arjacsoh Nov 04 '11 at 11:28
  • That does not change the fact that one *can* write dragging functionality with it that is persistent. – H.B. Nov 04 '11 at 12:21

2 Answers2

2

What you did is a possible implementation but in WPF there exists already a Control which is made for being dragged around: the Thumb.

example:

      <Canvas Width="200" Height="200" Background="Yellow">
            <Thumb x:Name="DragThumb"  DragDelta="Mover_DragDelta" Canvas.Top="20" Canvas.Left="10" Background="Gray" Width="50" Height="50" >
                <Thumb.Template>
                    <ControlTemplate>
                        <Rectangle Fill="Black" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
        </Canvas>

with a very simple code behind:

private void Mover_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
    Canvas.SetLeft(DragThumb, Canvas.GetLeft(DragThumb) + e.HorizontalChange);
    Canvas.SetTop(DragThumb, Canvas.GetTop(DragThumb) + e.VerticalChange);
}

already moves your canvas. (and it stays as the Canvas.Top / Canvas.Left Positions got set).

fixagon
  • 5,506
  • 22
  • 26
  • Ok, is it though possible to add more shapes on thumb in order to build a composite shape? Or should I wrap a child canvas in it and put the shapes on the child canvas? – arjacsoh Nov 04 '11 at 11:03
  • of course you can add any content in the Thumb as you want. You can just update the ControlTemplate and add whatever you want. – fixagon Nov 04 '11 at 13:25
1

You could use Canvas.Left and Canvas.Top property instead of mocking around with the RenderTransform.

Canvas.SetLeft(this, Canvas.GetLeft(this) + delta.X);
Canvas.SetTop(this, Canvas.GetTop(this) + delta.Y);
GeirGrusom
  • 999
  • 5
  • 18