Skip to content

Instantly share code, notes, and snippets.

@chugh97
Forked from cabrel/drag-drop-wpf.cs
Created December 22, 2015 17:25
Show Gist options
  • Save chugh97/580dee6b1f3d5118a7f8 to your computer and use it in GitHub Desktop.
Save chugh97/580dee6b1f3d5118a7f8 to your computer and use it in GitHub Desktop.
Drag & Drop in C# w/ WPF
// WPF Canvas Object
// Canvas LayoutCanvas;
//
// Events Required
//
// Canvas_PreviewMouseLeftButtonDown
// Canvas_PreviewMouseMove
// Canvas_PreviewMouseLeftButtonUp
// Parent_PreviewKeyDown
//
// LayoutCanvas.PreviewMouseLeftButtonDown += LayoutCanvas_PreviewMouseLeftButtonDown;
// LayoutCanvas.PreviewMouseMove += LayoutCanvas_PreviewMouseMove;
// LayoutCanvas.PreviewMouseLeftButtonUp += LayoutCanvas_PreviewMouseLeftButtonUp;
// WindowOrPage.PreviewKeyDown += WindowOrPage_PreviewKeyDown;
//
// Parameters Required
//
// For capturing the mouse position:
// Point ddStartPoint;
//
// The top left corner of the child object (left = x, top = y)
// double ddOriginalLeft;
// double ddOriginalTop;
//
// Properties for managing the state of the drag & drop process:
// bool ddIsMouseDown;
// bool ddIsBeingDragged;
//
// Our original UI element (in my case the children are all Image objects)
// UIElement ddOriginalElement;
//
// The container of the above element when we are in dragging mode
// System.Windows.Shapes.Rectangle ddOverlay;
//
//
// Canvas_PreviewMouseLeftButtonDown
//
// We assign this to our Canvas object as it will control
// catching whether or not we are clicking on the canvas itself
// or on one of its children
//
private void LayoutCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// If the source of the click is our canvas object then we want
// to exit because we are looking for it's children to drag
// and not the canvas itself.
if(e.Source == LayoutCanvas)
{
return;
}
// Identifies that we have started dragging
ddIsMouseDown = true;
// Captures the mouse position in the layout canvas
ddStartPoint = e.GetPosition(LayoutCanvas);
// Sets up our element that we will be dragging
ddOriginalElement = (UIElement)e.Source;
// Tells the Window to give the mouse to the LayoutCanvas
// object.
LayoutCanvas.CaptureMouse();
e.Handled = true;
}
//
// Canvas_PreviewMouseMove
//
// Our event handler for updating the position of our
// dragged element
//
// This introduces two helper methods DragStarted() and DragMoved()
// They will be covered later on in the code.
//
private void LayoutCanvas_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if(ddIsMouseDown)
{
if(!ddIsBeingDragged)
{
// Capture our mouse position relative to the LayoutCanvas object
var mousePosition = e.GetPosition(LayoutCanvas);
// Creates a transparent rectangle around our current drag point and we want to
// check here that we are within that rectangle
if(Math.Abs(mousePosition.X - ddStartPoint.X) > SystemParameters.MinimumHorizontalDragDistance &&
Math.Abs(mousePosition.Y - ddStartPoint.Y) > SystemParameters.MinimumVeritcalDragDistance)
{
DragStarted();
}
}
else
{
DragMoved();
}
}
}
//
// Canvas_PreviewMouseLeftButtonUp
//
// Controls the functionality for finishing our drag and drop process.
// This will also introduce the call to DragFinished(bool state);
//
private void LayoutCanvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
// This is a fairly simple check. If we are still dragging
// or starting to drag which means ddIsMouseDown would be 'True'
// then we don't stop the drag
if(ddIsMouseDown)
{
DragFinished(false);
}
}
//
// Page_PreviewKeydown
//
// In my code I have my canvas in a Page, you can do this with a Window object as well.
//
private void Page_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if(e.Key == Key.Escape && ddIsBeingDragged)
{
DragFinished = true;
}
}
// Helper Methods
//
// DragStarted()
//
//
private void DragStarted()
{
// Capture our last remaining properties
// needed to support our drag and drop
// process
ddIsBeingDragged = true;
ddOriginalLeft = Canvas.GetLeft(ddOriginalElement);
ddOriginalTop = Canvas.GetTop(ddOriginalElement);
// What we are doing here is creating a semi-transparent
// mirror image of the object we are dragging.
//
// This allows us to visually see that we have selected
// an object and are dragging it.
var brush = new VisualBrush(ddOriginalElement);
brush.Opacity = 0.5;
ddOverlay = new System.Windows.Shapes.Rectangle();
ddOverlay.Width = ddOriginalElement.RenderSize.Width;
ddOverlay.Height = ddOriginalElement.RenderSize.Height;
ddOverlay.Fill = brush;
// Finally add the overlay to the LayoutCanvas for displaying
LayoutCanvas.Children.Add(ddOverlay);
}
//
// DragMoved();
//
private void DragMoved()
{
// Capture the current mouse position, this will be used
// to redraw the overlay element we created in DragStarted()
var currentPosition = System.Windows.Input.Mouse.GetPosition(LayoutCanvas);
var elementLeft = (currentPosition.X - ddStartPoint.X) + ddOriginalLeft;
var elementTop = (currentPosition.Y - ddStartPoint.Y) + ddOriginalTop;
// We update the overlay's position on the LayoutCanvas
// by setting it's top left corner position below
Canvas.SetLeft(ddOverlay, elementLeft);
Canvas.SetTop(ddOverlay, elementTop);
}
//
// DragFinished();
//
private void DragFinished(bool canceled)
{
if(ddOverlay != null)
{
// capture our current position
var topLeft = Canvas.GetLeft(ddOverlay);
var top = Canvas.GetTop(ddOverlay);
if(ddIsBeingDragged)
{
LayoutCanvas.Children.Remove(ddOverlay);
// If it wasn't prematurely canceled, then
// move the element to the current mouse position
if(!canceled)
{
Canvas.SetLeft(ddOriginalElement, topLeft);
Canvas.SetTop(ddOriginalElement, top);
}
// Release the mouse from the layoutcanvas.
// This is very important. If you do not release the mouse
// you have to set the focus of the mouse to another application
// and then back again to regain mouse control
LayoutCanvas.ReleaseMouseCapture();
// Reset our drag & drop properties
ddOverlay = null;
ddIsMouseBeingDragged = false;
ddIsMouseDown = false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment