4

I've encountered a weird behavior when trying to use a thumb to move a control around on a canvas. When I add a control to a canvas and use Thumb DragDelta event to move it around everything looks good. But when I apply a rotate transform to the control dragging it around is bizarre. The control starts to circle around the cursor, and the bigger the angle the bigger the circle.

Does anyone know how to make thumb work with a transformed element? I've spent all day trying to figure it out and nothing smart is coming to my mind.

Thanks for your help!

chiefanov
  • 1,044
  • 1
  • 10
  • 15

4 Answers4

8

If you apply any rotating transform to FrameworkElement it means that the coordinates grid associated with it has rotated. Thus, any event handler of this FrameworkElement will be receive position values in own coordinates grid.

void DragThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
    //You can use this values when RotateTransform is null
    double deltaHorizontal = e.HorizontalChange;
    double deltaVertical = e.VerticalChange;

    //Transform coordinates
    Vector v = Math2DHelper.RotateVector2d(e.HorizontalChange, e.VerticalChange, Math2DHelper.D2R(rotationInDegrees));

    //Right values
    deltaHorizontal = v.X;
    deltaVertical = v.Y;

    ...
}

Sample math2D helper

public static class Math2DHelper
{
    public static Vector RotateVector2d(double x0, double y0, double rad)
    {
        Vector result = new Vector();
        result.X = x0 * Math.Cos(rad) - y0 * Math.Sin(rad);
        result.Y = x0 * Math.Sin(rad) + y0 * Math.Cos(rad);
        return result;
    }

    public static double D2R(double degree)
    {
        return (degree%360)*Math.PI/180;
    }
}
qwerty176
  • 81
  • 1
  • 7
4

I came across this problem and found the solution , maybe someone find it helpful ,you need to check for any transformation before drag thumb

private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        var thumb = dts as UIElement;
        var transform = thumb.RenderTransform as RotateTransform;
        Point dragDelta = new Point(e.HorizontalChange, e.VerticalChange);

            if (transform != null)
            {
                dragDelta = transform.Transform(dragDelta);
            }

            Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + dragDelta.X);
            Canvas.SetTop(thumb, Canvas.GetTop(thumb) + dragDelta.Y);

    }
Amir
  • 155
  • 3
  • 16
1

If you ditch the Canvas properties and apply the movement in the right order in a TransformGroup it should work:

<Thumb.RenderTransform>
    <TransformGroup>
        <TranslateTransform x:Name="translation" />
        <RotateTransform ... />
    </TransformGroup>
</Thumb.RenderTransform>
translation.X += e.HorizontalChange;
translation.Y += e.VerticalChange;

If you switch the order in the group you get the same behavior as when using Canvas.Left/Top.

(If you animated the rotation this will not help you)

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • This works better, but Rotation is now done around the left top corner of the canvas and not around the rotated item itself. Any suggestion on how to get that fixed? – chiefanov Feb 15 '12 at 15:52
  • So you are animating the rotation? – H.B. Feb 15 '12 at 15:55
  • No. I am calling InvalidateMeasure() on rotated item at the end of DragDelta event. Would that affect it? – chiefanov Feb 15 '12 at 16:02
  • Possibly, when only using the above code it did not rotate for me. – H.B. Feb 15 '12 at 16:05
  • I think what is going on is this: my original item location is 0,0. I move item using translate transform to a 50,50 location. When rotation is applied, rotation is centered around 0,0 as its items actual non-translated location. – chiefanov Feb 15 '12 at 16:15
  • 1
    I think I figured out a solution that will work for me. Instead of using e.HorizontalChange and e.VerticalChange I just use mouse position in the canvas at the end of the drag to figure out where my object should be moved. Its not exactly precise, but I think it will do for what I'm trying to achieve. – chiefanov Feb 16 '12 at 16:44
0

It appears that Thumb's HorizontalChange and VerticalChange don't play nicely when thumb is rotated. So, I'm just using cursor location in the canvas get my left and top offsets. Its not exactly accurate, but its close enough for what I'm trying to do.

chiefanov
  • 1,044
  • 1
  • 10
  • 15