using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.Media.Transformation; using Avalonia.Xaml.Interactivity; namespace Avalonia.Xaml.Interactions.Custom; /// /// /// public class ItemNudgeDropBehavior : StyledElementBehavior { /// /// /// public static readonly StyledProperty OrientationProperty = AvaloniaProperty.Register(nameof(Orientation), defaultValue: Orientation.Vertical); /// /// /// public Orientation Orientation { get => GetValue(OrientationProperty); set => SetValue(OrientationProperty, value); } /// protected override void OnAttachedToVisualTree() { AssociatedObject?.AddHandler(DragDrop.DragLeaveEvent, OnDragLeave); AssociatedObject?.AddHandler(DragDrop.DragOverEvent, OnDragOver); AssociatedObject?.AddHandler(DragDrop.DropEvent, OnDrop); } /// protected override void OnDetachedFromVisualTree() { AssociatedObject?.RemoveHandler(DragDrop.DragLeaveEvent, OnDragLeave); AssociatedObject?.RemoveHandler(DragDrop.DragOverEvent, OnDragOver); AssociatedObject?.RemoveHandler(DragDrop.DropEvent, OnDrop); } private void ApplyTranslation(Control control, double x, double y) { var transformBuilder = new TransformOperations.Builder(1); transformBuilder.AppendTranslate(x, y); control.RenderTransform = transformBuilder.Build(); } private void RemoveTranslations(object? sender) { if (sender is ItemsControl itemsControl) { foreach (var container in itemsControl.GetRealizedContainers()) { ApplyTranslation(container, 0, 0); } } } private void OnDrop(object? sender, DragEventArgs e) { RemoveTranslations(sender); } private void OnDragLeave(object? sender, RoutedEventArgs e) { RemoveTranslations(sender); } private void OnDragOver(object? sender, DragEventArgs e) { if (sender is not ItemsControl itemsControl) return; var isHorizontal = Orientation == Orientation.Horizontal; var dragPosition = e.GetPosition(itemsControl); for (int index = 0; index < itemsControl.ItemCount; index++) { var container = itemsControl.ContainerFromIndex(index); if (container == null) continue; var containerMidPoint = isHorizontal ? container.Bounds.Center.X : container.Bounds.Center.Y; var translationX = isHorizontal && dragPosition.X <= containerMidPoint ? container.Bounds.Width : 0; var translationY = !isHorizontal && dragPosition.Y <= containerMidPoint ? container.Bounds.Height : 0; ApplyTranslation(container, translationX, translationY); } } }