Recently, I needed to support dragging shapes and some other elements on a Canvas in WPF. However, looking online I found several implementations that were more complex than needed and/or not well functioning and I just wanted something very simple and solid. For that reason, below you will find a simple, yet useful implementation which can be easily adapted according to you needs.

Step 1: Create a WPF C# Project and add a Canvas in the main window

<Window x:Class="Canvas_Test.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas  Margin="0" >

    </Canvas>
</Window>

Step 2: Create your shapes inside the canvas

<Window x:Class="Canvas_Test.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas  Margin="0" >
        <Rectangle Width="50" Height="50"  Fill="Red" />
        <Rectangle Width="50" Height="50"  Fill="Green"  />
        <Rectangle Width="50" Height="50"  Fill="Blue" />
    </Canvas>
</Window>

Step 3: Write the proper handlers in the cs

 public partial class MainWindow : Window
    {
        protected bool isDragging;
        private Point clickPosition;
        private TranslateTransform originTT; 

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var draggableControl = sender as Shape;
            originTT = draggableControl.RenderTransform as TranslateTransform ?? new TranslateTransform();    
            isDragging = true;
            clickPosition = e.GetPosition(this);
            draggableControl.CaptureMouse();
        }

        private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isDragging = false;
            var draggable = sender as Shape;
            draggable.ReleaseMouseCapture();        
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            var draggableControl = sender as Shape;
            if (isDragging && draggableControl != null)
            {
                Point currentPosition = e.GetPosition(this);
                var transform = draggableControl.RenderTransform as TranslateTransform ?? new TranslateTransform();             
                transform.X = originTT.X+ (currentPosition.X - clickPosition.X);
                transform.Y =originTT.Y+ (currentPosition.Y - clickPosition.Y);
                draggableControl.RenderTransform = new TranslateTransform(transform.X, transform.Y);
            }
        }
    }

Step 4: Assign the proper handlers to the shapes

<Window x:Class="Canvas_Test.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas  Margin="0" >
        <Rectangle Width="50" Height="50"  Fill="Red" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseMove="Canvas_MouseMove" />
        <Rectangle Width="50" Height="50"  Fill="Green" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseMove="Canvas_MouseMove" />
        <Rectangle Width="50" Height="50"  Fill="Blue" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseMove="Canvas_MouseMove"/>
    </Canvas>
</Window>

Below is the final output – you will be able to drag-move the boxes around the window

You can also clone the project from github: https://github.com/devcoons/wpf-csharp-canvas-move-items

Author

Write A Comment