DraggAnimatedPanel.Drag.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*Developed by (doiTTeam)=>doiTTeam.mail = [email protected]*/
  2. using System;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Input;
  6. using System.Windows.Media;
  7. namespace DraggAnimatedPanel
  8. {
  9. /// <summary>
  10. /// Description of SafariPanel_Drag.
  11. /// </summary>
  12. public partial class DraggAnimatedPanel
  13. {
  14. #region const drag
  15. const double mouseDif = 2d;
  16. const int mouseTimeDif = 25;
  17. #endregion
  18. #region private
  19. UIElement __draggedElement;
  20. public UIElement _draggedElement
  21. {
  22. get { return __draggedElement; }
  23. set
  24. {
  25. __draggedElement = value;
  26. }
  27. }
  28. int _draggedIndex;
  29. bool _firstScrollRequest = true;
  30. ScrollViewer _scrollContainer;
  31. ScrollViewer scrollViewer
  32. {
  33. get
  34. {
  35. if (_firstScrollRequest && _scrollContainer == null)
  36. {
  37. _firstScrollRequest = false;
  38. _scrollContainer = (ScrollViewer)GetParent(this as DependencyObject, (ve) => ve is ScrollViewer);
  39. }
  40. return _scrollContainer;
  41. }
  42. }
  43. #endregion
  44. #region private drag
  45. double _lastMousePosX;
  46. double _lastMousePosY;
  47. int _lastMouseMoveTime;
  48. double _x;
  49. double _y;
  50. Rect _rectOnDrag;
  51. #endregion
  52. void OnMouseMove(object sender, MouseEventArgs e)
  53. {
  54. if (e.LeftButton == MouseButtonState.Pressed && _draggedElement == null && !this.IsMouseCaptured)
  55. StartDrag(e);
  56. else if (_draggedElement != null)
  57. OnDragOver(e);
  58. }
  59. void OnDragOver(MouseEventArgs e)
  60. {
  61. Point mousePos = Mouse.GetPosition(this);
  62. double difX = mousePos.X - _lastMousePosX;
  63. double difY = mousePos.Y - _lastMousePosY;
  64. int timeDif = e.Timestamp - _lastMouseMoveTime;
  65. if ((Math.Abs(difX) > mouseDif || Math.Abs(difY) > mouseDif) && timeDif > mouseTimeDif)
  66. {
  67. //this lines is for keepn draged item inside control bounds
  68. DoScroll();
  69. if (_x + difX < _rectOnDrag.Location.X)
  70. _x = 0;
  71. else if (ItemsWidth + _x + difX > _rectOnDrag.Location.X + _rectOnDrag.Width)
  72. _x = _rectOnDrag.Location.X + _rectOnDrag.Width - ItemsWidth;
  73. else if (mousePos.X > _rectOnDrag.Location.X && mousePos.X < _rectOnDrag.Location.X + _rectOnDrag.Width)
  74. _x += difX;
  75. if (_y + difY < _rectOnDrag.Location.Y)
  76. _y = 0;
  77. else if (ItemsHeight + _y + difY > _rectOnDrag.Location.Y + _rectOnDrag.Height)
  78. _y = _rectOnDrag.Location.Y + _rectOnDrag.Height - ItemsHeight;
  79. else if (mousePos.Y > _rectOnDrag.Location.Y && mousePos.Y < _rectOnDrag.Location.Y + _rectOnDrag.Height)
  80. _y += difY;
  81. //lines ends
  82. AnimateTo(_draggedElement, _x, _y, 0);
  83. _lastMousePosX = mousePos.X;
  84. _lastMousePosY = mousePos.Y;
  85. _lastMouseMoveTime = e.Timestamp;
  86. SwapElement(_x + ItemsWidth / 2, _y + ItemsHeight / 2);
  87. }
  88. }
  89. void StartDrag(MouseEventArgs e)
  90. {
  91. Point mousePos = Mouse.GetPosition(this);
  92. _draggedElement = GetChildThatHasMouseOver();
  93. if (_draggedElement == null)
  94. return;
  95. _draggedIndex = Children.IndexOf(_draggedElement);
  96. _rectOnDrag = VisualTreeHelper.GetDescendantBounds(this);
  97. Point p = GetItemVisualPoint(_draggedElement);
  98. _x = p.X;
  99. _y = p.Y;
  100. SetZIndex(_draggedElement, 1000);
  101. _lastMousePosX = mousePos.X;
  102. _lastMousePosY = mousePos.Y;
  103. _lastMouseMoveTime = e.Timestamp;
  104. this.InvalidateArrange();
  105. e.Handled = true;
  106. this.CaptureMouse();
  107. }
  108. void OnMouseUp(object sender, MouseEventArgs e)
  109. {
  110. if (this.IsMouseCaptured)
  111. ReleaseMouseCapture();
  112. }
  113. void SwapElement(double x, double y)
  114. {
  115. int index = GetIndexFromPoint(x, y);
  116. if (index == _draggedIndex || index < 0)
  117. return;
  118. if (index >= Children.Count)
  119. index = Children.Count - 1;
  120. int[] parameter = new int[] { _draggedIndex, index };
  121. if (SwapCommand != null && SwapCommand.CanExecute(parameter))
  122. {
  123. SwapCommand.Execute(parameter);
  124. _draggedElement = Children[index]; //this is bcause after changing the collection the element is other
  125. FillNewDraggedChild(_draggedElement);
  126. _draggedIndex = index;
  127. }
  128. this.InvalidateArrange();
  129. }
  130. void FillNewDraggedChild(UIElement child)
  131. {
  132. if (child.RenderTransform as TransformGroup == null)
  133. {
  134. child.RenderTransformOrigin = new Point(0.5, 0.5);
  135. TransformGroup group = new TransformGroup();
  136. child.RenderTransform = group;
  137. group.Children.Add(new TranslateTransform());
  138. }
  139. SetZIndex(child, 1000);
  140. AnimateTo(child, _x, _y, 0); //need relocate the element
  141. }
  142. void OnLostMouseCapture(object sender, MouseEventArgs e)
  143. {
  144. FinishDrag();
  145. }
  146. void FinishDrag()
  147. {
  148. if (_draggedElement != null)
  149. {
  150. SetZIndex(_draggedElement, 0);
  151. _draggedElement = null;
  152. this.InvalidateArrange();
  153. }
  154. }
  155. void DoScroll()
  156. {
  157. if (scrollViewer != null)
  158. {
  159. Point position = Mouse.GetPosition(scrollViewer);
  160. double scrollMargin = Math.Min(scrollViewer.FontSize * 2, scrollViewer.ActualHeight / 2);
  161. if (position.X >= scrollViewer.ActualWidth - scrollMargin &&
  162. scrollViewer.HorizontalOffset < scrollViewer.ExtentWidth - scrollViewer.ViewportWidth)
  163. {
  164. scrollViewer.LineRight();
  165. }
  166. else if (position.X < scrollMargin && scrollViewer.HorizontalOffset > 0)
  167. {
  168. scrollViewer.LineLeft();
  169. }
  170. else if (position.Y >= scrollViewer.ActualHeight - scrollMargin &&
  171. scrollViewer.VerticalOffset < scrollViewer.ExtentHeight - scrollViewer.ViewportHeight)
  172. {
  173. scrollViewer.LineDown();
  174. }
  175. else if (position.Y < scrollMargin && scrollViewer.VerticalOffset > 0)
  176. {
  177. scrollViewer.LineUp();
  178. }
  179. }
  180. }
  181. }
  182. }