123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Threading.Tasks;
- using Avalonia.Controls;
- using Avalonia.Input;
- using Avalonia.Interactivity;
- using Avalonia.Xaml.Interactivity;
- namespace Avalonia.Xaml.Interactions.DragAndDrop;
- /// <summary>
- ///
- /// </summary>
- public class TypedDragBehavior : StyledElementBehavior<Control>
- {
- private Point _dragStartPoint;
- private PointerEventArgs? _triggerEvent;
- private object? _value;
- private bool _lock;
- /// <summary>
- ///
- /// </summary>
- public static readonly StyledProperty<Type?> DataTypeProperty =
- AvaloniaProperty.Register<TypedDragBehavior, Type?>(nameof(DataType));
- /// <summary>
- ///
- /// </summary>
- public static readonly StyledProperty<IDragHandler?> HandlerProperty =
- AvaloniaProperty.Register<TypedDragBehavior, IDragHandler?>(nameof(Handler));
- /// <summary>
- ///
- /// </summary>
- public Type? DataType
- {
- get => GetValue(DataTypeProperty);
- set => SetValue(DataTypeProperty, value);
- }
- /// <summary>
- ///
- /// </summary>
- public IDragHandler? Handler
- {
- get => GetValue(HandlerProperty);
- set => SetValue(HandlerProperty, value);
- }
- /// <inheritdoc />
- protected override void OnAttachedToVisualTree()
- {
- AssociatedObject?.AddHandler(InputElement.PointerPressedEvent, AssociatedObject_PointerPressed, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
- AssociatedObject?.AddHandler(InputElement.PointerReleasedEvent, AssociatedObject_PointerReleased, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
- AssociatedObject?.AddHandler(InputElement.PointerMovedEvent, AssociatedObject_PointerMoved, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
- }
- /// <inheritdoc />
- protected override void OnDetachedFromVisualTree()
- {
- AssociatedObject?.RemoveHandler(InputElement.PointerPressedEvent, AssociatedObject_PointerPressed);
- AssociatedObject?.RemoveHandler(InputElement.PointerReleasedEvent, AssociatedObject_PointerReleased);
- AssociatedObject?.RemoveHandler(InputElement.PointerMovedEvent, AssociatedObject_PointerMoved);
- }
- private async Task DoDragDrop(PointerEventArgs triggerEvent, object? value)
- {
- var data = new DataObject();
- data.Set(ContextDropBehavior.DataFormat, value!);
- var effect = DragDropEffects.None;
- if (triggerEvent.KeyModifiers.HasFlag(KeyModifiers.Alt))
- {
- effect |= DragDropEffects.Link;
- }
- else if (triggerEvent.KeyModifiers.HasFlag(KeyModifiers.Shift))
- {
- effect |= DragDropEffects.Move;
- }
- else if (triggerEvent.KeyModifiers.HasFlag(KeyModifiers.Control))
- {
- effect |= DragDropEffects.Copy;
- }
- else
- {
- effect |= DragDropEffects.Move;
- }
- await DragDrop.DoDragDrop(triggerEvent, data, effect);
- }
- private void AssociatedObject_PointerPressed(object? sender, PointerPressedEventArgs e)
- {
- var properties = e.GetCurrentPoint(AssociatedObject).Properties;
- if (properties.IsLeftButtonPressed)
- {
- if (e.Source is Control control
- && AssociatedObject?.DataContext == control.DataContext
- && DataType is not null
- && DataType.IsInstanceOfType(control.DataContext))
- {
- _dragStartPoint = e.GetPosition(null);
- _triggerEvent = e;
- _value = control.DataContext;
- _lock = true;
- }
- }
- }
- private void AssociatedObject_PointerReleased(object? sender, PointerReleasedEventArgs e)
- {
- var properties = e.GetCurrentPoint(AssociatedObject).Properties;
- if (properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased && _triggerEvent is not null)
- {
- _triggerEvent = null;
- _value = null;
- _lock = false;
- }
- }
- private async void AssociatedObject_PointerMoved(object? sender, PointerEventArgs e)
- {
- var properties = e.GetCurrentPoint(AssociatedObject).Properties;
- if (properties.IsLeftButtonPressed && _triggerEvent is not null)
- {
- var point = e.GetPosition(null);
- var diff = _dragStartPoint - point;
- if (Math.Abs(diff.X) > 3 || Math.Abs(diff.Y) > 3)
- {
- if (_lock)
- {
- _lock = false;
- }
- else
- {
- return;
- }
- Handler?.BeforeDragDrop(sender, _triggerEvent, _value);
- await DoDragDrop(_triggerEvent, _value);
- Handler?.AfterDragDrop(sender, _triggerEvent, _value);
- _triggerEvent = null;
- _value = null;
- }
- }
- }
- }
|