WPF: How to draw a circle and drag it around?

17,271

Solution 1

"whatever it is" matters because placement of elements in WPF is highly dependent on the parent container. It's easy to move something 20px to the right inside a Canvas (just add to Canvas.Left), but it's much harder to do so in a Grid (you have to deal with Column, ColumnSpan and Margin).

There's a code project article describing how to drag elements inside a Canvas: Dragging Elements in a Canvas

If you want to move just that circle and not other controls in an existing Canvas/Grid; I suggest you use a DragCanvas (from the article) as an overlay over the normal Canvas/Grid.

As for the 'draw a circle' part: just use an Ellipse as element inside the DragCanvas.

Solution 2

I would define a canvas and an ellipse in the XAML file:

<Canvas Background="White" Name="canvas" Width="950" Height="500" MouseDown="MouseMove">
    <Ellipse Name="bola" Canvas.Left="130" Canvas.Top="79" Width="50" Height="50" Fill="Green"  />
</Canvas>

Notice that canvas has the attribute MouseDown="MouseMoveFunction". Whenever you click on the canvas, that event handler will be called. In case you want it to move as your mouse moves, use MouseMove="MouseMoveFunction"

Then just update the ellipse's position everytime you move your mouse. The following code goes in the function that is called on mouse events:

    private void MouseMove(object sender, MouseEventArgs e)
    {
        Point punto = e.GetPosition(canvas);
        int mouseX = (int)punto.X;
        int mouseY = (int)punto.Y;
        bola.SetValue(Canvas.LeftProperty, (double)mouseX); //set x
        bola.SetValue(Canvas.TopProperty, (double)mouseY); //set y

    }

Solution 3

I was able to do this all in code, but unable to move the Ellipse element that was a child element of my canvas.

I've copied the code below so you can reproduce it.
First create a WPF app called WPFExample and make sure your main form has the following:

<Window x:Class="WPFExample.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"
        xmlns:local="clr-namespace:WPFExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Background="LightGray">
    <Grid>
        <Canvas HorizontalAlignment="Left" Name="MainCanvas"
                Height="300" Width="500" Margin="5,5,5,5" VerticalAlignment="Top" Background="LightYellow" MouseDown="Canvas_MouseDown" MouseMove="MainCanvas_MouseMove"
                />
        <Ellipse Name="post" Width="50" Height="50" Fill="Red" Margin="5,5,5,5"  />

    </Grid>
</Window>

Next, add the code to your main form:

       private void Draw(Point m)
        {
            MainCanvas.Children.Clear();

            int mX = (int)m.X;
            int mY = (int)m.Y;
            Ellipse el = new Ellipse();
            el.Width = 15;
            el.Height = 15;
            el.SetValue(Canvas.LeftProperty, (Double)mX);
            el.SetValue(Canvas.TopProperty, (Double)mY);
            el.Fill = Brushes.Black;

            MainCanvas.Children.Add(el);
        }

        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Draw(e.GetPosition(MainCanvas));
        }

        private void MainCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            Draw(e.GetPosition(MainCanvas));
        }

Obviously, focus on the Draw() method. Notice that I Clear the canvas each time through. Then I draw the new Ellipse in the mouse location as a black circle.

Now each time you move your mouse the black circle is erased from the canvas, created again and then drawn in the new location. Here's a snapshot of the app -- when you run it and move the mouse the black circle will be redrawn wherever you move your mouse, as if you are dragging it around. black circle redraw

The red ellipse was problematic for me and I could never get it to redraw and couldn't remove it from the list of children and add it again for this quick example.

Share:
17,271
Pratik Deoghare
Author by

Pratik Deoghare

Updated on July 03, 2022

Comments

  • Pratik Deoghare
    Pratik Deoghare almost 2 years

    I am new to WPF.

    I want to draw a small circle on Canvas when I click mouse and be able to drag it around smoothly.

    How can I accomplish this?

  • Pratik Deoghare
    Pratik Deoghare over 14 years
    Ok. I am using Canvas and done with drawing but dragging is still a problem. Can you provide small code snippet?
  • raddevus
    raddevus over 7 years
    FYI - That code in the MouseMove doesn't quite work. I put the code in my WPF app and debugged it. I can see each of the lines stepped onto but the Ellipse is never redrawn in the new location. Is there some way to call Invalidate() on the canvas rect or something? Not sure, but this doesn't work.
  • mgear
    mgear over 2 years
    Note: If the canvas doesn't have background color, mousemove and click wont register there. (so i placed my mousemove event to the image behind invisible canvas)