Ivan Cortes
Ivan Cortes

Reputation: 35

Shaking in dragging object

I am new to C#. I have been testing in C# (wpf) with MouseDown and MouseMove. Try to create a simple ellipse that can be dragged with the click and movement of the mouse, within a canvas. All good until I run the code and I see that when I drag the ellipse it shakes. I know for some it's not a problem, but for me it is. Next the code in xaml that I use.

<Canvas>
        <Ellipse x:Name="circulito" Fill="#FFFDC347" Height="100" Stroke="Black"  Width="100"
        MouseDown="circulito_MouseDown"
        MouseMove="circulito_MouseMove"/>
</Canvas>

Next the code in c#.

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        Point coor;
        Point coorPutin;

        private void circulito_MouseDown(object sender, MouseButtonEventArgs e)
        {
            coor.X = Canvas.GetLeft(this);
            coor.Y = Canvas.GetTop(this);
        }

        private void circulito_MouseMove(object sender, MouseEventArgs e)
        {            
            coorPutin = e.GetPosition(circulito);                        

            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                Canvas.SetLeft(circulito, coor.X + coorPutin.X);
                Canvas.SetTop(circulito, coor.Y + coorPutin.Y);
            }
        }

Upvotes: 1

Views: 380

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112632

I think that in MouseMove you should use the position of the mouse within the canvas. Therefore assign it a name

<Canvas x:Name="canvas">

Then you can set the position of the ellipse with

public void circulito_MouseMove(object sender, MouseEventArgs e)
{
    if (Mouse.LeftButton == MouseButtonState.Pressed) {
        var coorPutin = e.GetPosition(canvas);
        Canvas.SetLeft(circulito, coorPutin.X - coor.X);
        Canvas.SetTop(circulito, coorPutin.Y - coor.Y);
    }
}

Also, you must subtract the initial position you got from MouseDown, since you want to set the top/left position of the ellipse above and and to the left of the mouse position to maintain the relative position of the mouse cursor in the ellipse.

Canvas.GetLeft(this); will return NaN (not a number) if it has not been initialized. Therefore it is better to use

public void circulito_MouseDown(object sender, MouseButtonEventArgs e)
{
    coor = e.GetPosition(circulito);
}

Upvotes: 0

Ivan Cortes
Ivan Cortes

Reputation: 35

Thank you very much for answering me Codexer. The xaml code leaves it the same. In the end just change the c # code to the following.

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        Point coor;

        private void circulito_MouseDown(object sender, MouseButtonEventArgs e)
        {
            coor = e.GetPosition(circulito);
        }

        private void circulito_MouseMove(object sender, MouseEventArgs e)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                circulito.SetValue(Canvas.LeftProperty, e.GetPosition(this).X - coor.X);
                circulito.SetValue(Canvas.TopProperty, e.GetPosition(this).Y - coor.Y);
            }
        }
    }

Upvotes: 0

Trevor
Trevor

Reputation: 8004

All good until I run the code and I see that when I drag the ellipse it shakes

The reason for this is because of your circulito_MouseMove routine. You don't need to check if the button is down or not also you are trying to set the canvas, this wont work, you need to set the element (Ellipse) TopProperty and LeftProperty. Please see below for working solution.

MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        private Ellipse _ellipse;
        private Point? _coor;

        public MainWindow() { InitializeComponent(); }

        private void circulito_MouseDown(object sender, MouseButtonEventArgs e)
        {
            _ellipse = sender as Ellipse;
            _coor = e.GetPosition(_ellipse);
        }

        private void circulito_MouseMove(object sender, MouseEventArgs e)
        {
            if (_ellipse == null)
                return;

            _ellipse.SetValue(Canvas.LeftProperty, e.GetPosition(this).X - _coor.Value.X);
            _ellipse.SetValue(Canvas.TopProperty, e.GetPosition(this).Y - _coor.Value.Y);
        }

        private void circulito_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => _ellipse = null;

    }

MainWindow.xaml

<Window x:Class="WpfApp12.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"       
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="800"
        Height="450"
        mc:Ignorable="d"
        MouseMove="circulito_MouseMove"
        >
    <Canvas>
        <Ellipse x:Name="circulito"
                 Width="100"
                 Height="100"
                 Fill="#FFFDC347"
                 Stroke="Black"
                 MouseLeftButtonDown="circulito_MouseDown"
                 MouseLeftButtonUp="circulito_MouseLeftButtonUp"
                 MouseMove="circulito_MouseMove"
                 />
    </Canvas>
</Window>

Please note in the MainWindow.xaml Window element, you need to handle the MouseMove event as well...

 MouseMove="circulito_MouseMove"

enter image description here

Upvotes: 1

Related Questions