Created
May 10, 2014 11:16
-
-
Save JannikArndt/7c2fc2eb998bf2ffc89f to your computer and use it in GitHub Desktop.
Custom Drag and Drop with multiple Canvas-elements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="WPFTryOut.MainWindow" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
Title="MainWindow" Height="350" Width="525"> | |
<Grid> | |
<Canvas Name="rootCanvas" ZIndex="1"> | |
<Canvas Name="Canvas2" Width="100" Height="100" ZIndex="0" Background="Aquamarine" Left="30" Top="30" MouseLeftButtonDown="DragStart" MouseMove="Drag" PreviewMouseLeftButtonUp="DragEnd"> | |
<Rectangle Canvas.Left="10" Canvas.Top="10" Width="20" Height="20" Fill="Blue" MouseLeftButtonDown="DragStart" MouseMove="Drag" PreviewMouseLeftButtonUp="DragEnd"></Rectangle> | |
<Rectangle Canvas.Left="40" Canvas.Top="60" Width="20" Height="20" Fill="Red" MouseLeftButtonDown="DragStart" MouseMove="Drag" PreviewMouseLeftButtonUp="DragEnd"></Rectangle> | |
</Canvas> | |
<Canvas Name="Canvas3" Width="100" Height="100" ZIndex="0" Background="Aquamarine" Left="330" Top="30" MouseLeftButtonDown="DragStart" MouseMove="Drag" PreviewMouseLeftButtonUp="DragEnd"> | |
</Canvas> | |
</Canvas> | |
</Grid> | |
</Window> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Input; | |
using System.Windows.Media; | |
namespace WPFTryOut | |
{ | |
/// <summary> | |
/// Interaction logic for MainWindow.xaml | |
/// </summary> | |
public partial class MainWindow | |
{ | |
public MainWindow() | |
{ | |
InitializeComponent(); | |
} | |
bool _captured; | |
double _left, _top, _canvasX, _canvasY, _originalLeft, _originalTop; | |
UIElement _draggedElement; | |
private Canvas _draggedOverCanvas; | |
private Canvas _originalParentCanvas; | |
private void DragStart(object sender, MouseButtonEventArgs e) | |
{ | |
_draggedElement = (UIElement)sender; | |
Mouse.Capture(_draggedElement); | |
_captured = true; | |
// Store original situation for possible reset | |
_originalParentCanvas = (Canvas)LogicalTreeHelper.GetParent(_draggedElement); | |
_originalLeft = Canvas.GetLeft(_draggedElement); | |
_originalTop = Canvas.GetTop(_draggedElement); | |
// store coordinates | |
_left = _originalLeft; | |
_top = _originalTop; | |
_canvasX = e.GetPosition(rootCanvas).X; | |
_canvasY = e.GetPosition(rootCanvas).Y; | |
// For objects in another canvas, check if it is not the root canvas, than change the parent to the root canvas and update coordinates. | |
// While in drag-mode, the element belongs to the root canvas. | |
if (_originalParentCanvas != null && _originalParentCanvas != rootCanvas && _originalParentCanvas.Children.Contains(_draggedElement)) | |
{ | |
_originalParentCanvas.Children.Remove(_draggedElement); | |
rootCanvas.Children.Add(_draggedElement); | |
_left += Canvas.GetLeft(_originalParentCanvas); | |
_top += Canvas.GetTop(_originalParentCanvas); | |
} | |
// Do not drag any other objects | |
e.Handled = true; | |
} | |
private void Drag(object sender, MouseEventArgs e) | |
{ | |
if (_captured) | |
{ | |
// Get new mouse position relative to root canvas | |
double x = e.GetPosition(rootCanvas).X; | |
double y = e.GetPosition(rootCanvas).Y; | |
// Change left and top of UIElement by the mouse-movement (new position - old position) | |
_left += x - _canvasX; | |
_top += y - _canvasY; | |
Canvas.SetLeft(_draggedElement, _left); | |
Canvas.SetTop(_draggedElement, _top); | |
// Store new mouse position | |
_canvasX = x; | |
_canvasY = y; | |
// Highlight (or UNhighlight) the canvas you are dragging over. Also: Store it (as a future target). | |
var hitTestResult = VisualTreeHelper.HitTest(rootCanvas, e.GetPosition(rootCanvas)); | |
if (hitTestResult != null && hitTestResult.VisualHit != null) | |
{ | |
var hit = hitTestResult.VisualHit as Canvas; | |
if (hit != null && hit != _draggedOverCanvas) | |
{ | |
if (_draggedOverCanvas != null) | |
_draggedOverCanvas.Background = Brushes.Aquamarine; | |
_draggedOverCanvas = hit; | |
hit.Background = Brushes.Yellow; | |
} | |
} | |
else | |
{ | |
if (_draggedOverCanvas != null) | |
_draggedOverCanvas.Background = Brushes.Aquamarine; | |
_draggedOverCanvas = null; | |
} | |
} | |
e.Handled = true; | |
} | |
private void DragEnd(object sender, MouseButtonEventArgs e) | |
{ | |
Mouse.Capture(null); | |
_captured = false; | |
// if there is a target canvas | |
if (_draggedOverCanvas != null) | |
{ | |
_draggedOverCanvas.Background = Brushes.Aquamarine; | |
// and you are not dragging a canvas itself | |
if (_draggedElement.GetType() != typeof(Canvas)) | |
{ | |
// add the element to the new canvas | |
rootCanvas.Children.Remove(_draggedElement); | |
_draggedOverCanvas.Children.Add(_draggedElement); | |
// and update its coordinates | |
var newLeft = _left - Canvas.GetLeft(_draggedOverCanvas); | |
var newTop = _top - Canvas.GetTop(_draggedOverCanvas); | |
Canvas.SetLeft(_draggedElement, newLeft); | |
Canvas.SetTop(_draggedElement, newTop); | |
} | |
_draggedOverCanvas = null; | |
} | |
// otherwise reset the element to its original position | |
else | |
{ | |
if (_draggedElement.GetType() != typeof(Canvas)) | |
{ | |
// add the element to the original canvas | |
rootCanvas.Children.Remove(_draggedElement); | |
_originalParentCanvas.Children.Add(_draggedElement); | |
// and restore its coordinates | |
Canvas.SetLeft(_draggedElement, _originalLeft); | |
Canvas.SetTop(_draggedElement, _originalTop); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment