Skip to content

Instantly share code, notes, and snippets.

@georg-jung
Last active January 4, 2023 14:45
Show Gist options
  • Save georg-jung/e6825e9cbafd0a5a13a8d2677ecfa634 to your computer and use it in GitHub Desktop.
Save georg-jung/e6825e9cbafd0a5a13a8d2677ecfa634 to your computer and use it in GitHub Desktop.
Drop files behavior for WinUI 3.
using Microsoft.UI.Xaml;
using Windows.ApplicationModel.DataTransfer;
namespace App1.Helpers;
// based on https://stackoverflow.com/a/65266427/1200847
public interface IFilesDropped
{
void OnFilesDropped(string[] files);
}
public class DropFilesBehavior
{
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled", typeof(bool), typeof(DropFilesBehavior), PropertyMetadata.Create(default(bool), OnIsEnabledChanged));
public static readonly DependencyProperty FileDropTargetProperty = DependencyProperty.RegisterAttached(
"FileDropTarget", typeof(IFilesDropped), typeof(DropFilesBehavior), null);
public static void SetIsEnabled(DependencyObject element, bool value)
{
element.SetValue(IsEnabledProperty, value);
}
public static bool GetIsEnabled(DependencyObject element)
{
return (bool)element.GetValue(IsEnabledProperty);
}
public static void SetFileDropTarget(DependencyObject obj, IFilesDropped value)
{
obj.SetValue(FileDropTargetProperty, value);
}
public static IFilesDropped GetFileDropTarget(DependencyObject obj)
{
return (IFilesDropped)obj.GetValue(FileDropTargetProperty);
}
private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = d as FrameworkElement ?? throw new InvalidOperationException();
if ((bool)e.NewValue)
{
fe.AllowDrop = true;
fe.Drop += OnDrop;
fe.DragOver += OnDragOver;
}
else
{
fe.AllowDrop = false;
fe.Drop -= OnDrop;
fe.DragOver -= OnDragOver;
}
}
private static void OnDragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Move; // or Link/Copy
e.Handled = true;
}
private static void OnDrop(object sender, DragEventArgs e)
{
var dobj = (DependencyObject)sender;
var target = dobj.GetValue(FileDropTargetProperty);
var filesDropped = target switch
{
IFilesDropped fd => fd,
null => throw new InvalidOperationException("File drop target is not set."),
_ => throw new InvalidOperationException($"Binding error, '{target.GetType().Name}' doesn't implement '{nameof(IFilesDropped)}'."),
};
if (filesDropped == null)
{
return;
}
var files = e.DataView.GetStorageItemsAsync().GetAwaiter().GetResult();
if (files.Count == 0)
{
return;
}
filesDropped.OnFilesDropped(files.Select(f => f.Path).ToArray());
}
}
<Page
x:Class="App1.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="using:App1.Helpers"
Background="{ThemeResource SolidBackgroundFillColorBaseBrush}"
mc:Ignorable="d">
<Grid x:Name="ContentArea" helpers:DropFilesBehavior.IsEnabled="True" helpers:DropFilesBehavior.FileDropTarget="{x:Bind ViewModel}">
</Grid>
</Page>
using App1.Helpers;
namespace App1.ViewModels;
public partial class ViewModel : ObservableRecipient, IFilesDropped
{
public ViewModel()
{
}
public void OnFilesDropped(string[] files)
{
Debug.Print("---");
foreach (var file in files)
{
Debug.Print($"{file}");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment