---
name: implementing-wpf-dragdrop
description: Implements WPF drag and drop functionality using DragDrop.DoDragDrop, DataObject, and drag/drop events. Use when building file drop zones, list reordering, or inter-application data transfer.
---
# WPF Drag and Drop Patterns
Implementing drag and drop functionality for data transfer within and between applications.
**Advanced Patterns:** See [ADVANCED.md](ADVANCED.md) for visual feedback, list reordering, and custom data formats.
## 1. Drag and Drop Overview
```
Drag Source Drop Target
│ │
├─ MouseDown │
├─ MouseMove (drag threshold) │
├─ DragDrop.DoDragDrop()───────────────┤
│ ├─ DragEnter
│ ├─ DragOver
│ ├─ DragLeave
│ └─ Drop
└─ GiveFeedback (cursor change)
```
---
## 2. Basic Drag Source
### 2.1 Simple Text Drag
```csharp
namespace MyApp.Views;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
public partial class DragSourceView : UserControl
{
private Point _startPoint;
private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
private void TextBlock_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
return;
var currentPoint = e.GetPosition(null);
var diff = _startPoint - currentPoint;
// Check if drag threshold is exceeded
if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
{
if (sender is TextBlock textBlock)
{
// Create data object and start drag
var data = new DataObject(DataFormats.Text, textBlock.Text);
DragDrop.DoDragDrop(textBlock, data, DragDropEffects.Copy);
}
}
}
}
```
### 2.2 Multiple Data Formats
```csharp
private void StartDragWithMultipleFormats(FrameworkElement source, object item)
{
var data = new DataObject();
// Add multiple formats for compatibility
if (item is MyDataItem dataItem)
{
data.SetData(typeof(MyDataItem), dataItem);
data.SetData(DataFormats.Text, dataItem.ToString());
data.SetData(DataFormats.Serializable, dataItem);
}
DragDrop.DoDragDrop(source, data, DragDropEffects.Copy | DragDropEffects.Move);
}
```
---
## 3. Drop Target
### 3.1 Basic Drop Target
```xml
```
```csharp
private void DropZone_DragEnter(object sender, DragEventArgs e)
{
// Check if data format is acceptable
if (!e.Data.GetDataPresent(DataFormats.FileDrop) &&
!e.Data.GetDataPresent(DataFormats.Text))
{
e.Effects = DragDropEffects.None;
}
else
{
e.Effects = DragDropEffects.Copy;
HighlightDropZone(true);
}
e.Handled = true;
}
private void DropZone_DragOver(object sender, DragEventArgs e)
{
// Continuously update effects based on position or modifier keys
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = (e.KeyStates & DragDropKeyStates.ControlKey) != 0
? DragDropEffects.Copy
: DragDropEffects.Move;
}
e.Handled = true;
}
private void DropZone_DragLeave(object sender, DragEventArgs e)
{
HighlightDropZone(false);
}
private void DropZone_Drop(object sender, DragEventArgs e)
{
HighlightDropZone(false);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
ProcessDroppedFiles(files);
}
else if (e.Data.GetDataPresent(DataFormats.Text))
{
var text = (string)e.Data.GetData(DataFormats.Text);
ProcessDroppedText(text);
}
e.Handled = true;
}
```
---
## 4. File Drop Zone Control
```csharp
namespace MyApp.Controls;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
public sealed partial class FileDropZone : UserControl
{
public static readonly DependencyProperty AcceptedExtensionsProperty =
DependencyProperty.Register(
nameof(AcceptedExtensions),
typeof(string[]),
typeof(FileDropZone),
new PropertyMetadata(new[] { "*" }));
public string[] AcceptedExtensions
{
get => (string[])GetValue(AcceptedExtensionsProperty);
set => SetValue(AcceptedExtensionsProperty, value);
}
public event EventHandler>? FilesDropped;
public FileDropZone()
{
InitializeComponent();
AllowDrop = true;
}
protected override void OnDragEnter(DragEventArgs e)
{
ValidateAndSetEffects(e);
}
protected override void OnDragOver(DragEventArgs e)
{
ValidateAndSetEffects(e);
}
protected override void OnDrop(DragEventArgs e)
{
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
return;
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
var validFiles = FilterValidFiles(files);
if (validFiles.Count > 0)
{
FilesDropped?.Invoke(this, validFiles);
}
}
private void ValidateAndSetEffects(DragEventArgs e)
{
e.Effects = DragDropEffects.None;
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Handled = true;
return;
}
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (FilterValidFiles(files).Count > 0)
{
e.Effects = DragDropEffects.Copy;
}
e.Handled = true;
}
private List FilterValidFiles(string[] files)
{
var result = new List();
foreach (var file in files)
{
if (!File.Exists(file))
continue;
var extension = Path.GetExtension(file).ToLowerInvariant();
if (AcceptedExtensions.Contains("*") ||
AcceptedExtensions.Contains(extension))
{
result.Add(file);
}
}
return result;
}
}
```
### Usage
```xml
```
---
## 5. DragDropEffects
| Effect | Description | Cursor |
|--------|-------------|--------|
| **None** | Drop not allowed | No-drop cursor |
| **Copy** | Copy data | Copy cursor (+) |
| **Move** | Move data | Move cursor |
| **Link** | Create link | Link cursor |
| **Scroll** | Scrolling occurring | Scroll cursor |
| **All** | Copy, Move, Scroll combined | - |
```csharp
private void DropZone_DragOver(object sender, DragEventArgs e)
{
// Set effect based on modifier keys
if ((e.KeyStates & DragDropKeyStates.ControlKey) != 0)
{
e.Effects = DragDropEffects.Copy;
}
else if ((e.KeyStates & DragDropKeyStates.ShiftKey) != 0)
{
e.Effects = DragDropEffects.Move;
}
else if ((e.KeyStates & DragDropKeyStates.AltKey) != 0)
{
e.Effects = DragDropEffects.Link;
}
else
{
e.Effects = DragDropEffects.Move; // Default
}
}
```
---
## 6. References
- [Drag and Drop Overview - Microsoft Docs](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/drag-and-drop-overview)
- [DataObject Class - Microsoft Docs](https://learn.microsoft.com/en-us/dotnet/api/system.windows.dataobject)
- [DragDrop Class - Microsoft Docs](https://learn.microsoft.com/en-us/dotnet/api/system.windows.dragdrop)