Skip to content

Commit d961dbe

Browse files
Merge pull request #13 from danwalmsley/item-nudge-behavior
Behavior to nudge items out the way during drag drop operations.
2 parents 6dda3ca + fee71e2 commit d961dbe

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Input;
3+
using Avalonia.Interactivity;
4+
using Avalonia.Layout;
5+
using Avalonia.Media.Transformation;
6+
using Avalonia.Xaml.Interactivity;
7+
8+
namespace Avalonia.Xaml.Interactions.Custom;
9+
10+
/// <summary>
11+
///
12+
/// </summary>
13+
public class ItemNudgeDropBehavior : StyledElementBehavior<ItemsControl>
14+
{
15+
/// <summary>
16+
///
17+
/// </summary>
18+
public static readonly StyledProperty<Orientation> OrientationProperty =
19+
AvaloniaProperty.Register<ItemNudgeDropBehavior, Orientation>(nameof(Orientation),
20+
defaultValue: Orientation.Vertical);
21+
22+
/// <summary>
23+
///
24+
/// </summary>
25+
public Orientation Orientation
26+
{
27+
get => GetValue(OrientationProperty);
28+
set => SetValue(OrientationProperty, value);
29+
}
30+
31+
/// <inheritdoc />
32+
protected override void OnAttachedToVisualTree()
33+
{
34+
AssociatedObject?.AddHandler(DragDrop.DragLeaveEvent, OnDragLeave);
35+
AssociatedObject?.AddHandler(DragDrop.DragOverEvent, OnDragOver);
36+
AssociatedObject?.AddHandler(DragDrop.DropEvent, OnDrop);
37+
}
38+
39+
/// <inheritdoc />
40+
protected override void OnDetachedFromVisualTree()
41+
{
42+
AssociatedObject?.RemoveHandler(DragDrop.DragLeaveEvent, OnDragLeave);
43+
AssociatedObject?.RemoveHandler(DragDrop.DragOverEvent, OnDragOver);
44+
AssociatedObject?.RemoveHandler(DragDrop.DropEvent, OnDrop);
45+
}
46+
47+
private void ApplyTranslation(Control control, double x, double y)
48+
{
49+
var transformBuilder = new TransformOperations.Builder(1);
50+
transformBuilder.AppendTranslate(x, y);
51+
control.RenderTransform = transformBuilder.Build();
52+
}
53+
54+
private void RemoveTranslations(object? sender)
55+
{
56+
if (sender is ItemsControl itemsControl)
57+
{
58+
foreach (var container in itemsControl.GetRealizedContainers())
59+
{
60+
ApplyTranslation(container, 0, 0);
61+
}
62+
}
63+
}
64+
65+
private void OnDrop(object? sender, DragEventArgs e)
66+
{
67+
RemoveTranslations(sender);
68+
}
69+
70+
private void OnDragLeave(object? sender, RoutedEventArgs e)
71+
{
72+
RemoveTranslations(sender);
73+
}
74+
75+
private void OnDragOver(object? sender, DragEventArgs e)
76+
{
77+
if (sender is not ItemsControl itemsControl) return;
78+
79+
var isHorizontal = Orientation == Orientation.Horizontal;
80+
81+
var dragPosition = e.GetPosition(itemsControl);
82+
83+
for (int index = 0; index < itemsControl.ItemCount; index++)
84+
{
85+
var container = itemsControl.ContainerFromIndex(index);
86+
87+
if (container == null) continue;
88+
89+
var containerMidPoint = isHorizontal ? container.Bounds.Center.X : container.Bounds.Center.Y;
90+
91+
var translationX = isHorizontal && dragPosition.X <= containerMidPoint ? container.Bounds.Width : 0;
92+
var translationY = !isHorizontal && dragPosition.Y <= containerMidPoint ? container.Bounds.Height : 0;
93+
94+
ApplyTranslation(container, translationX, translationY);
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)