WPF Drag & Drop: How to detect when drag is started
This article will explain how to detect when drag is started in WPF Applications.
Complete Visual Studio 2010 Solution
https://docs.google.com/file/d/0Bw72YL7u1BpmQkl3Q3BleDgzR1E/edit?usp=sharing
Features:
1) Reliably detect drag & drop
2) Don't confuse double clicks as drag start
3) Don't confuse scrolling as drag event
Notes:
- WPF is very powerful, but one thing i find missing is an event telling developers when drag is started
- The solution here involves handling Left Button Down, Mouse Move & Left Button Up event combinations to detect when drag & drop is started and when it ended
Important:
Even though the code posted here uses code-behind, I highly recommend using MVVM way of handling drag & drop using attached properties on controls to detect drag & drop, show visual feedback and transfer data. (I will post a WPF MVVM Drag & Drop Framework soon)
Complete Visual Studio 2010 Solution
https://docs.google.com/file/d/0Bw72YL7u1BpmQkl3Q3BleDgzR1E/edit?usp=sharing
XAML:
<Window x:Class="DragAndDropDragStart.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF Drag and Drop: detect when drag is started" Height="200" Width="200"> <Grid> <TextBlock Text="Drag me!" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="25" Foreground="RoyalBlue" MouseLeftButtonDown="OnDragSourceMouseLeftButtonDown" MouseLeftButtonUp="OnDragSourceMouseLeftButtonUp" MouseMove="OnDragSourceMouseMove"/> </Grid> </Window>
Code-Behind:
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace DragAndDropDragStart
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
private Point _dragStartPoint;
private bool _isMouseDown;
public MainWindow()
{
InitializeComponent();
}
private void OnDragSourceMouseLeftButtonDown(object sender,
MouseButtonEventArgs e)
{
if (e.ClickCount != 1)
{
return;
}
_dragStartPoint = e.GetPosition(e.Source as FrameworkElement);
_isMouseDown = true;
}
private void OnDragSourceMouseMove(object sender, MouseEventArgs e)
{
if (_isMouseDown &&
IsDragGesture(e.GetPosition(e.Source as FrameworkElement)))
{
if (ReferenceEquals(null,
FindAncestor<ScrollBar>((DependencyObject)e.OriginalSource)))
{
// Drag Started
_isMouseDown = false;
Mouse.Capture(sender as UIElement);
MessageBox.Show("Drag Started");
}
}
}
private void OnDragSourceMouseLeftButtonUp(object sender,
MouseButtonEventArgs e)
{
_isMouseDown = false;
Mouse.Capture(null);
}
private bool IsDragGesture(Point point)
{
var horizontalMove = Math.Abs(point.X - _dragStartPoint.X);
var verticalMove = Math.Abs(point.Y - _dragStartPoint.Y);
var hGesture = horizontalMove >
SystemParameters.MinimumHorizontalDragDistance;
var vGesture = verticalMove >
SystemParameters.MinimumVerticalDragDistance;
return (hGesture | vGesture);
}
private static T FindAncestor<T>(DependencyObject dependencyObject)
where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindAncestor<T>(parent);
}
}
}
Comments
Post a Comment