GridDragBehavior.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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 GridDragBehavior : StyledElementBehavior<Control>
  11. {
  12. /// <summary>
  13. ///
  14. /// </summary>
  15. public static readonly StyledProperty<bool> CopyColumnProperty =
  16. AvaloniaProperty.Register<GridDragBehavior, bool>(nameof(CopyColumn), true);
  17. /// <summary>
  18. ///
  19. /// </summary>
  20. public static readonly StyledProperty<bool> CopyRowProperty =
  21. AvaloniaProperty.Register<GridDragBehavior, bool>(nameof(CopyRow), true);
  22. /// <summary>
  23. ///
  24. /// </summary>
  25. public static readonly StyledProperty<bool> CopyColumnSpanProperty =
  26. AvaloniaProperty.Register<GridDragBehavior, bool>(nameof(CopyColumnSpan));
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. public static readonly StyledProperty<bool> CopyRowSpanProperty =
  31. AvaloniaProperty.Register<GridDragBehavior, bool>(nameof(CopyRowSpan));
  32. private bool _enableDrag;
  33. private Control? _parent;
  34. private Control? _draggedContainer;
  35. private Control? _adorner;
  36. private bool _captured;
  37. /// <summary>
  38. ///
  39. /// </summary>
  40. public bool CopyColumn
  41. {
  42. get => GetValue(CopyColumnProperty);
  43. set => SetValue(CopyColumnProperty, value);
  44. }
  45. /// <summary>
  46. ///
  47. /// </summary>
  48. public bool CopyRow
  49. {
  50. get => GetValue(CopyRowProperty);
  51. set => SetValue(CopyRowProperty, value);
  52. }
  53. /// <summary>
  54. ///
  55. /// </summary>
  56. public bool CopyColumnSpan
  57. {
  58. get => GetValue(CopyColumnSpanProperty);
  59. set => SetValue(CopyColumnSpanProperty, value);
  60. }
  61. /// <summary>
  62. ///
  63. /// </summary>
  64. public bool CopyRowSpan
  65. {
  66. get => GetValue(CopyRowSpanProperty);
  67. set => SetValue(CopyRowSpanProperty, value);
  68. }
  69. /// <inheritdoc />
  70. protected override void OnAttachedToVisualTree()
  71. {
  72. if (AssociatedObject is not null)
  73. {
  74. AssociatedObject.AddHandler(InputElement.PointerReleasedEvent, Released, RoutingStrategies.Tunnel);
  75. AssociatedObject.AddHandler(InputElement.PointerPressedEvent, Pressed, RoutingStrategies.Tunnel);
  76. AssociatedObject.AddHandler(InputElement.PointerMovedEvent, Moved, RoutingStrategies.Tunnel);
  77. AssociatedObject.AddHandler(InputElement.PointerCaptureLostEvent, CaptureLost, RoutingStrategies.Tunnel);
  78. }
  79. }
  80. /// <inheritdoc />
  81. protected override void OnDetachedFromVisualTree()
  82. {
  83. if (AssociatedObject is not null)
  84. {
  85. AssociatedObject.RemoveHandler(InputElement.PointerReleasedEvent, Released);
  86. AssociatedObject.RemoveHandler(InputElement.PointerPressedEvent, Pressed);
  87. AssociatedObject.RemoveHandler(InputElement.PointerMovedEvent, Moved);
  88. AssociatedObject.RemoveHandler(InputElement.PointerCaptureLostEvent, CaptureLost);
  89. }
  90. }
  91. private void AddAdorner(Control control)
  92. {
  93. var layer = AdornerLayer.GetAdornerLayer(control);
  94. if (layer is null)
  95. {
  96. return;
  97. }
  98. _adorner = new SelectionAdorner()
  99. {
  100. [AdornerLayer.AdornedElementProperty] = control
  101. };
  102. ((ISetLogicalParent) _adorner).SetParent(control);
  103. layer.Children.Add(_adorner);
  104. }
  105. private void RemoveAdorner(Control control)
  106. {
  107. var layer = AdornerLayer.GetAdornerLayer(control);
  108. if (layer is null || _adorner is null)
  109. {
  110. return;
  111. }
  112. layer.Children.Remove(_adorner);
  113. ((ISetLogicalParent) _adorner).SetParent(null);
  114. _adorner = null;
  115. }
  116. private void Pressed(object? sender, PointerPressedEventArgs e)
  117. {
  118. var properties = e.GetCurrentPoint(AssociatedObject).Properties;
  119. if (properties.IsLeftButtonPressed
  120. && AssociatedObject?.Parent is Control parent)
  121. {
  122. _enableDrag = true;
  123. _parent = parent;
  124. _draggedContainer = AssociatedObject;
  125. SetDraggingPseudoClasses(_draggedContainer, true);
  126. // AddAdorner(_draggedContainer);
  127. _captured = true;
  128. }
  129. }
  130. private void Released(object? sender, PointerReleasedEventArgs e)
  131. {
  132. if (_captured)
  133. {
  134. if (e.InitialPressMouseButton == MouseButton.Left)
  135. {
  136. Released();
  137. }
  138. _captured = false;
  139. }
  140. }
  141. private void CaptureLost(object? sender, PointerCaptureLostEventArgs e)
  142. {
  143. Released();
  144. _captured = false;
  145. }
  146. private void Moved(object? sender, PointerEventArgs e)
  147. {
  148. var properties = e.GetCurrentPoint(AssociatedObject).Properties;
  149. if (_captured
  150. && properties.IsLeftButtonPressed)
  151. {
  152. if (_parent is null || _draggedContainer is null || !_enableDrag)
  153. {
  154. return;
  155. }
  156. var position = e.GetPosition(_parent);
  157. Control? target = null;
  158. if (_parent is Grid grid)
  159. {
  160. foreach (var child in grid.Children)
  161. {
  162. if (Equals(child, _draggedContainer))
  163. {
  164. continue;
  165. }
  166. if (child.Bounds.Contains(position) && child is Control control)
  167. {
  168. target = control;
  169. }
  170. }
  171. }
  172. else if (_parent is ItemsControl itemsControl)
  173. {
  174. foreach (var control in itemsControl.GetRealizedContainers())
  175. {
  176. if (control is null)
  177. {
  178. continue;
  179. }
  180. if (Equals(control, _draggedContainer))
  181. {
  182. continue;
  183. }
  184. if (control.Bounds.Contains(position))
  185. {
  186. target = control;
  187. }
  188. }
  189. }
  190. else
  191. {
  192. return;
  193. }
  194. if (target is null)
  195. {
  196. return;
  197. }
  198. var copyColumn = CopyColumn;
  199. var copyRow = CopyRow;
  200. var copyColumnSpan = CopyColumnSpan;
  201. var copyRowSpan = CopyRowSpan;
  202. var sourceColumn = Grid.GetColumn(_draggedContainer);
  203. var sourceRow = Grid.GetRow(_draggedContainer);
  204. var sourceColumnSpan = Grid.GetColumnSpan(_draggedContainer);
  205. var sourceRowSpan = Grid.GetRowSpan(_draggedContainer);
  206. var targetColumn = Grid.GetColumn(target);
  207. var targetRow = Grid.GetRow(target);
  208. var targetColumnSpan = Grid.GetColumnSpan(target);
  209. var targetRowSpan = Grid.GetRowSpan(target);
  210. if (copyColumn)
  211. {
  212. Grid.SetColumn(_draggedContainer, targetColumn);
  213. }
  214. if (copyRow)
  215. {
  216. Grid.SetRow(_draggedContainer, targetRow);
  217. }
  218. if (copyColumnSpan)
  219. {
  220. Grid.SetColumnSpan(_draggedContainer, targetColumnSpan);
  221. }
  222. if (copyRowSpan)
  223. {
  224. Grid.SetRowSpan(_draggedContainer, targetRowSpan);
  225. }
  226. if (copyColumn)
  227. {
  228. Grid.SetColumn(target, sourceColumn);
  229. }
  230. if (copyRow)
  231. {
  232. Grid.SetRow(target, sourceRow);
  233. }
  234. if (copyColumnSpan)
  235. {
  236. Grid.SetColumnSpan(target, sourceColumnSpan);
  237. }
  238. if (copyRowSpan)
  239. {
  240. Grid.SetRowSpan(target, sourceRowSpan);
  241. }
  242. }
  243. }
  244. private void Released()
  245. {
  246. if (_enableDrag)
  247. {
  248. if (_parent is not null && _draggedContainer is not null)
  249. {
  250. // RemoveAdorner(_draggedContainer);
  251. }
  252. if (_draggedContainer is not null)
  253. {
  254. SetDraggingPseudoClasses(_draggedContainer, false);
  255. }
  256. _enableDrag = false;
  257. _parent = null;
  258. _draggedContainer = null;
  259. }
  260. }
  261. private void SetDraggingPseudoClasses(Control control, bool isDragging)
  262. {
  263. if (isDragging)
  264. {
  265. ((IPseudoClasses)control.Classes).Add(":dragging");
  266. }
  267. else
  268. {
  269. ((IPseudoClasses)control.Classes).Remove(":dragging");
  270. }
  271. }
  272. }