DragControlBehavior.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using Avalonia.Controls;
  2. using Avalonia.Input;
  3. using Avalonia.Media;
  4. using Avalonia.Xaml.Interactivity;
  5. namespace Avalonia.Xaml.Interactions.Custom;
  6. /// <summary>
  7. /// A behavior that allows controls to be moved around the canvas using RenderTransform of <see cref="IBehavior.AssociatedObject"/>.
  8. /// </summary>
  9. public sealed class DragControlBehavior : StyledElementBehavior<Control>
  10. {
  11. /// <summary>
  12. /// Identifies the <seealso cref="TargetControl"/> avalonia property.
  13. /// </summary>
  14. public static readonly StyledProperty<Control?> TargetControlProperty =
  15. AvaloniaProperty.Register<DragControlBehavior, Control?>(nameof(TargetControl));
  16. private Control? _parent;
  17. private Point _previous;
  18. /// <summary>
  19. /// Gets or sets the target control to be moved around instead of <see cref="IBehavior.AssociatedObject"/>. This is a avalonia property.
  20. /// </summary>
  21. [ResolveByName]
  22. public Control? TargetControl
  23. {
  24. get => GetValue(TargetControlProperty);
  25. set => SetValue(TargetControlProperty, value);
  26. }
  27. /// <inheritdoc />
  28. protected override void OnAttachedToVisualTree()
  29. {
  30. var source = AssociatedObject;
  31. if (source is not null)
  32. {
  33. source.PointerPressed += Source_PointerPressed;
  34. }
  35. }
  36. /// <inheritdoc />
  37. protected override void OnDetachedFromVisualTree()
  38. {
  39. var source = AssociatedObject;
  40. if (source is not null)
  41. {
  42. source.PointerPressed -= Source_PointerPressed;
  43. }
  44. _parent = null;
  45. }
  46. private void Source_PointerPressed(object? sender, PointerPressedEventArgs e)
  47. {
  48. var target = TargetControl ?? AssociatedObject;
  49. if (target is not null)
  50. {
  51. _parent = target.Parent as Control;
  52. if (!(target.RenderTransform is TranslateTransform))
  53. {
  54. target.RenderTransform = new TranslateTransform();
  55. }
  56. _previous = e.GetPosition(_parent);
  57. if (_parent != null)
  58. {
  59. _parent.PointerMoved += Parent_PointerMoved;
  60. _parent.PointerReleased += Parent_PointerReleased;
  61. }
  62. }
  63. }
  64. private void Parent_PointerMoved(object? sender, PointerEventArgs args)
  65. {
  66. var target = TargetControl ?? AssociatedObject;
  67. if (target is not null)
  68. {
  69. var pos = args.GetPosition(_parent);
  70. if (target.RenderTransform is TranslateTransform tr)
  71. {
  72. tr.X += pos.X - _previous.X;
  73. tr.Y += pos.Y - _previous.Y;
  74. }
  75. _previous = pos;
  76. }
  77. }
  78. private void Parent_PointerReleased(object? sender, PointerReleasedEventArgs e)
  79. {
  80. if (_parent is not null)
  81. {
  82. _parent.PointerMoved -= Parent_PointerMoved;
  83. _parent.PointerReleased -= Parent_PointerReleased;
  84. _parent = null;
  85. }
  86. }
  87. }