Evgeni Velikov
Evgeni Velikov

Reputation: 382

How can change position of canvas in WPF?

How can change runtime position of a canvas in which dynamically I added controls like (labels, lines)?

I can zoom canvas with all controls but I can't move in another position with MouseMove, MouseUp, MouseDown.

<Canvas Name="canvas" Width="1000" Height="400"
            Margin="100 0 0 50"
            Background="White"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Center"
            MouseWheel="Canvas_MouseWheel"
            MouseMove="Canvas_MouseMove"
            MouseUp="Canvas_MouseUp"
            MouseDown="Canvas_MouseDown">
        <Canvas.RenderTransform>
            <ScaleTransform x:Name="st" />
        </Canvas.RenderTransform>
    </Canvas>

I find this code in internet but for my case is not working

bool activated;
    Point point;

    private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        activated = true;
        point = Mouse.GetPosition(canvas);
        Mouse.Capture(canvas);
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (activated)
        {
            double top = Canvas.GetTop(canGraph) + Mouse.GetPosition(canvas).Y - point.Y;
            Canvas.SetTop(canvas, top);
            double left = Canvas.GetLeft(canvas) + Mouse.GetPosition(canvas).X - point.X;
            Canvas.SetLeft(canvas, left);
            point = Mouse.GetPosition(canvas);
        }
    }

    private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
    {
        activated = false;
        Mouse.Capture(null);
    }

Upvotes: 2

Views: 11466

Answers (2)

Andrea Brendy
Andrea Brendy

Reputation: 1

After mouse down then again I move the canvas is start to move from first position when is been.

P.s.

I add this for more stable code , but always return back to the first position

 private void Canvas_MouseLeave(object sender, MouseEventArgs e)
    {
        activated = false;
    }

Upvotes: 0

kirotab
kirotab

Reputation: 1306

Edit - The previous solution that I provided was not going to work after the first move of the element without more code so here's a better one

In order to be working correctly the canvas element have to be aligned to the coordinate system of it's parent, which we achieve as we put the canvas in top left corner, if you don't put it there you have to calculate the difference yourselve.

Code behind

private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        canvas.CaptureMouse();
    }

    Stopwatch sw = new Stopwatch();
    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (canvas.IsMouseCaptured)
        {
            translate.X = e.GetPosition(container).X;
            translate.Y = e.GetPosition(container).Y;
        }
    }

    private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
    {
        canvas.ReleaseMouseCapture();
    }

XAML

<Grid Background="Green" x:Name="container">
    <Canvas Name="canvas" Width="100" Height="100"
        Margin="0 0 0 0"
        Background="Purple"
        VerticalAlignment="Top"
        HorizontalAlignment="Left"
        MouseMove="Canvas_MouseMove"

        MouseDown="Canvas_MouseDown">
        <StackPanel Background="White">

        <TextBlock >asdasda</TextBlock>
        <TextBlock >cccc</TextBlock>
        <TextBlock >aaaaa</TextBlock>
        <TextBlock >bbbb</TextBlock>
        </StackPanel>
    <Canvas.RenderTransform>
            <TransformGroup>
                <ScaleTransform x:Name="st" />
                <TranslateTransform x:Name="translate" />
            </TransformGroup>
        </Canvas.RenderTransform>
</Canvas>
</Grid>

Original answer


XAML

I'd do something like this:

  • Add a translate transform and to keep you previous transform put it in a group

  • Use translate transform in order to move the canvas with positions from the mouse events

  • For starting point of your translations you can use coordinates in the container

Code behind:

bool activated;
    Point point;

    private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        activated = true;
        point = e.GetPosition(container);
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (activated)
        {
            translate.X = e.GetPosition(container).X - point.X;
            translate.Y = e.GetPosition(container).Y - point.Y;
        }
    }

    private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
    {
        activated = false;
    }

XAML

<Canvas Name="canvas" Width="100" Height="100"
        Margin="0 0 0 0"
        Background="Purple"
        VerticalAlignment="Stretch"
        HorizontalAlignment="Stretch"
        MouseMove="Canvas_MouseMove"
        MouseUp="Canvas_MouseUp"
        MouseDown="Canvas_MouseDown">
    <Canvas.RenderTransform>
            <TransformGroup>
                <ScaleTransform x:Name="st" />
                <TranslateTransform x:Name="translate" />
            </TransformGroup>
        </Canvas.RenderTransform>
</Canvas>
</Grid>

Upvotes: 5

Related Questions