Primary APIs:
DragDropDragEventArgsDragDropEffectsIDataTransfer, IAsyncDataTransferDataTransfer, DataTransferItemImportant members:
DragDrop.AllowDropPropertyDragDrop.DragEnterEvent, DragLeaveEvent, DragOverEvent, DropEventDragDrop.SetAllowDrop(...)DragDrop.AddDragOverHandler(...), AddDropHandler(...)DragDrop.DoDragDropAsync(...)DragEventArgs.DataTransfer, DragEffects, GetPosition(...)DataTransferItem.CreateText(...), CreateFile(...), Set(...)DataTransferExtensions.TryGetText(), TryGetFiles()Reference source files:
src/Avalonia.Base/Input/DragDrop.cssrc/Avalonia.Base/Input/DragEventArgs.cssrc/Avalonia.Base/Input/IDataTransfer.cssrc/Avalonia.Base/Input/DataTransfer.cssrc/Avalonia.Base/Input/DataTransferItem.cssrc/Avalonia.Base/Input/DataTransferExtensions.csTarget route model:
DragDrop.AllowDrop.DragOver and assign e.DragEffects.Drop and consume e.DataTransfer payload.Source model:
DataTransfer payload.DragDrop.DoDragDropAsync(triggerEvent, payload, allowedEffects).using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform.Storage;
public sealed class FileDropBehavior
{
public static void Attach(Control target, Action<IStorageItem[]> onFilesDropped)
{
DragDrop.SetAllowDrop(target, true);
target.AddHandler(DragDrop.DragOverEvent, (_, e) =>
{
IStorageItem[]? files = e.DataTransfer.TryGetFiles();
e.DragEffects = files is { Length: > 0 } ? DragDropEffects.Copy : DragDropEffects.None;
e.Handled = true;
});
target.AddHandler(DragDrop.DropEvent, (_, e) =>
{
IStorageItem[]? files = e.DataTransfer.TryGetFiles();
if (files is { Length: > 0 })
onFilesDropped(files);
e.Handled = true;
});
}
}
using System.Threading.Tasks;
using Avalonia.Input;
public static class DragSourceWorkflows
{
public static Task<DragDropEffects> StartTextDragAsync(PointerEventArgs trigger, string text)
{
DataTransfer payload = new();
payload.Add(DataTransferItem.CreateText(text));
return DragDrop.DoDragDropAsync(trigger, payload, DragDropEffects.Copy | DragDropEffects.Move);
}
}
Default mode:
XAML-first complete example:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.ViewModels"
x:DataType="vm:DragDropViewModel">
<Border Margin="12"
Padding="12"
BorderBrush="Gray"
BorderThickness="1"
DragDrop.AllowDrop="True">
<TextBlock Text="{CompiledBinding DropHint}" />
</Border>
</UserControl>
Code-only alternative (on request):
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Input;
public static class CodeOnlyDragDropSample
{
public static Control BuildDropSurface(Action<string> onText)
{
Border surface = new()
{
Padding = new Thickness(12),
BorderBrush = Brushes.Gray,
BorderThickness = new Thickness(1),
Child = new TextBlock { Text = "Drop text or files here" }
};
DragDrop.SetAllowDrop(surface, true);
surface.AddHandler(DragDrop.DropEvent, (_, e) =>
{
string? text = e.DataTransfer.TryGetText();
if (!string.IsNullOrEmpty(text))
onText(text);
e.Handled = true;
});
return surface;
}
}
DragEffects in DragOver for deterministic UX feedback.TryGetText, TryGetFiles) over raw format parsing.DragDrop.AllowDrop was not enabled.DragOver did not set e.DragEffects to a non-None value.None effect: