AvaloniaUI / Avalonia.Xaml.Behaviors

Port of Windows UWP Xaml Behaviors for Avalonia Xaml.
MIT License
385 stars 46 forks source link

Add support to IDragHandler to specify a produced object for the drag drop payload #111

Open stevemonaco opened 1 year ago

stevemonaco commented 1 year ago

Currently, ContentDragBehavior will forward only the binded Context into the drag+drop interaction. IDragHandler.BeforeDragDrop does not seem to allow for a produced value to be specified as the drag+drop payload.

Use case: I have an image editor where I make selections and drag+drop to replace contents. There is no backing collection and as such it doesn't work like a collection control. The source Context is the VM because there is logic that I want to run before drag initiated.

I want to produce the payload (an object with copied image data and/or tile metadata) at drag initiation because it's expensive to repeatedly create during selection. I also want the drag+drop interaction to "own" the payload at that point so that the source VM doesn't need to. I have already done this locally by extending IDragHandler and creating a modified ContextDragBehavior, though this is probably not an appropriate API for the library if you can break IDragHandler.BeforeDragDrop.

My local changes:

public interface IDragHandlerEx : IDragHandler
{
    public object? Payload { get; set; }
}

I have modified ContextDragBehavior to use IDragHandlerEx and this area of ContextDragBehavior to:

var context = Context ?? AssociatedObject?.DataContext;
Handler?.BeforeDragDrop(sender, _triggerEvent, context);

var payload = Handler?.Payload ?? context;
await DoDragDrop(_triggerEvent, payload);

Handler?.AfterDragDrop(sender, _triggerEvent, context); // This may need payload as an extra parameter