using System; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Platform.Storage; namespace ControlCatalog.Pages { public partial class DragAndDropPage : UserControl { private readonly DataFormat _customFormat = DataFormat.CreateStringApplicationFormat("xxx-avalonia-controlcatalog-custom"); public DragAndDropPage() { InitializeComponent(); int textCount = 0; SetupDnd( "Text", d => d.Add(DataTransferItem.Create(DataFormat.Text, $"Text was dragged {++textCount} times")), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link); SetupDnd( "Custom", d => d.Add(DataTransferItem.Create(_customFormat, "Test123")), DragDropEffects.Copy | DragDropEffects.Move); SetupDnd( "Files", async d => { if (Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName is { } name && TopLevel.GetTopLevel(this) is { } topLevel && await topLevel.StorageProvider.TryGetFileFromPathAsync(name) is { } storageFile) { d.Add(DataTransferItem.Create(DataFormat.File, storageFile)); } }, DragDropEffects.Copy); } private void SetupDnd(string suffix, Action factory, DragDropEffects effects) => SetupDnd( suffix, o => { factory(o); return Task.CompletedTask; }, effects); private void SetupDnd(string suffix, Func factory, DragDropEffects effects) { var dragMe = this.Get("DragMe" + suffix); var dragState = this.Get("DragState" + suffix); async void DoDrag(object? sender, PointerPressedEventArgs e) { var dragData = new DataTransfer(); await factory(dragData); var result = await DragDrop.DoDragDropAsync(e, dragData, effects); switch (result) { case DragDropEffects.Move: dragState.Text = "Data was moved"; break; case DragDropEffects.Copy: dragState.Text = "Data was copied"; break; case DragDropEffects.Link: dragState.Text = "Data was linked"; break; case DragDropEffects.None: dragState.Text = "The drag operation was canceled"; break; default: dragState.Text = "Unknown result"; break; } } void DragOver(object? sender, DragEventArgs e) { if (e.Source is Control c && c.Name == "MoveTarget") { e.DragEffects = e.DragEffects & (DragDropEffects.Move); } else { e.DragEffects = e.DragEffects & (DragDropEffects.Copy); } // Only allow if the dragged data contains text or filenames. if (!e.DataTransfer.Contains(DataFormat.Text) && !e.DataTransfer.Contains(DataFormat.File) && !e.DataTransfer.Contains(_customFormat)) e.DragEffects = DragDropEffects.None; } async void Drop(object? sender, DragEventArgs e) { if (e.Source is Control c && c.Name == "MoveTarget") { e.DragEffects = e.DragEffects & (DragDropEffects.Move); } else { e.DragEffects = e.DragEffects & (DragDropEffects.Copy); } if (e.DataTransfer.Contains(DataFormat.Text)) { DropState.Text = e.DataTransfer.TryGetText(); } else if (e.DataTransfer.Contains(DataFormat.File)) { var files = e.DataTransfer.TryGetFiles() ?? []; var contentStr = ""; foreach (var item in files) { if (item is IStorageFile file) { var content = await DialogsPage.ReadTextFromFile(file, 500); contentStr += $"File {item.Name}:{Environment.NewLine}{content}{Environment.NewLine}{Environment.NewLine}"; } else if (item is IStorageFolder folder) { var childrenCount = 0; await foreach (var _ in folder.GetItemsAsync()) { childrenCount++; } contentStr += $"Folder {item.Name}: items {childrenCount}{Environment.NewLine}{Environment.NewLine}"; } } DropState.Text = contentStr; } else if (e.DataTransfer.Contains(_customFormat)) { DropState.Text = "Custom: " + e.DataTransfer.TryGetValue(_customFormat); } } dragMe.PointerPressed += DoDrag; AddHandler(DragDrop.DropEvent, Drop); AddHandler(DragDrop.DragOverEvent, DragOver); } } }