CanvasDragBehavior.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using Avalonia.Controls;
  2. using Avalonia.Controls.Primitives;
  3. using Avalonia.Input;
  4. using Avalonia.Interactivity;
  5. using Avalonia.Xaml.Interactivity;
  6. namespace Avalonia.Xaml.Interactions.Draggable;
  7. /// <summary>
  8. ///
  9. /// </summary>
  10. public class CanvasDragBehavior : StyledElementBehavior<Control>
  11. {
  12. private bool _enableDrag;
  13. private Point _start;
  14. private Control? _parent;
  15. private Control? _draggedContainer;
  16. private Control? _adorner;
  17. private bool _captured;
  18. /// <inheritdoc />
  19. protected override void OnAttachedToVisualTree()
  20. {
  21. if (AssociatedObject is not null)
  22. {
  23. AssociatedObject.AddHandler(InputElement.PointerReleasedEvent, Released, RoutingStrategies.Tunnel);
  24. AssociatedObject.AddHandler(InputElement.PointerPressedEvent, Pressed, RoutingStrategies.Tunnel);
  25. AssociatedObject.AddHandler(InputElement.PointerMovedEvent, Moved, RoutingStrategies.Tunnel);
  26. AssociatedObject.AddHandler(InputElement.PointerCaptureLostEvent, CaptureLost, RoutingStrategies.Tunnel);
  27. }
  28. }
  29. /// <inheritdoc />
  30. protected override void OnDetachedFromVisualTree()
  31. {
  32. if (AssociatedObject is not null)
  33. {
  34. AssociatedObject.RemoveHandler(InputElement.PointerReleasedEvent, Released);
  35. AssociatedObject.RemoveHandler(InputElement.PointerPressedEvent, Pressed);
  36. AssociatedObject.RemoveHandler(InputElement.PointerMovedEvent, Moved);
  37. AssociatedObject.RemoveHandler(InputElement.PointerCaptureLostEvent, CaptureLost);
  38. }
  39. }
  40. private void AddAdorner(Control control)
  41. {
  42. var layer = AdornerLayer.GetAdornerLayer(control);
  43. if (layer is null)
  44. {
  45. return;
  46. }
  47. _adorner = new SelectionAdorner()
  48. {
  49. [AdornerLayer.AdornedElementProperty] = control
  50. };
  51. ((ISetLogicalParent) _adorner).SetParent(control);
  52. layer.Children.Add(_adorner);
  53. }
  54. private void RemoveAdorner(Control control)
  55. {
  56. var layer = AdornerLayer.GetAdornerLayer(control);
  57. if (layer is null || _adorner is null)
  58. {
  59. return;
  60. }
  61. layer.Children.Remove(_adorner);
  62. ((ISetLogicalParent) _adorner).SetParent(null);
  63. _adorner = null;
  64. }
  65. private void Pressed(object? sender, PointerPressedEventArgs e)
  66. {
  67. var properties = e.GetCurrentPoint(AssociatedObject).Properties;
  68. if (properties.IsLeftButtonPressed
  69. && AssociatedObject?.Parent is Control parent)
  70. {
  71. _enableDrag = true;
  72. _start = e.GetPosition(parent);
  73. _parent = parent;
  74. _draggedContainer = AssociatedObject;
  75. SetDraggingPseudoClasses(_draggedContainer, true);
  76. // AddAdorner(_draggedContainer);
  77. _captured = true;
  78. }
  79. }
  80. private void Released(object? sender, PointerReleasedEventArgs e)
  81. {
  82. if (_captured)
  83. {
  84. if (e.InitialPressMouseButton == MouseButton.Left)
  85. {
  86. Released();
  87. }
  88. _captured = false;
  89. }
  90. }
  91. private void CaptureLost(object? sender, PointerCaptureLostEventArgs e)
  92. {
  93. Released();
  94. _captured = false;
  95. }
  96. private void Moved(object? sender, PointerEventArgs e)
  97. {
  98. var properties = e.GetCurrentPoint(AssociatedObject).Properties;
  99. if (_captured
  100. && properties.IsLeftButtonPressed)
  101. {
  102. if (_parent is null || _draggedContainer is null || !_enableDrag)
  103. {
  104. return;
  105. }
  106. var position = e.GetPosition(_parent);
  107. var deltaX = position.X - _start.X;
  108. var deltaY = position.Y - _start.Y;
  109. _start = position;
  110. var left = Canvas.GetLeft(_draggedContainer);
  111. var top = Canvas.GetTop(_draggedContainer);
  112. Canvas.SetLeft(_draggedContainer, left + deltaX);
  113. Canvas.SetTop(_draggedContainer, top + deltaY);
  114. }
  115. }
  116. private void Released()
  117. {
  118. if (_enableDrag)
  119. {
  120. if (_parent is not null && _draggedContainer is not null)
  121. {
  122. // RemoveAdorner(_draggedContainer);
  123. }
  124. if (_draggedContainer is not null)
  125. {
  126. SetDraggingPseudoClasses(_draggedContainer, false);
  127. }
  128. _enableDrag = false;
  129. _parent = null;
  130. _draggedContainer = null;
  131. }
  132. }
  133. private void SetDraggingPseudoClasses(Control control, bool isDragging)
  134. {
  135. if (isDragging)
  136. {
  137. ((IPseudoClasses)control.Classes).Add(":dragging");
  138. }
  139. else
  140. {
  141. ((IPseudoClasses)control.Classes).Remove(":dragging");
  142. }
  143. }
  144. }