123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- using System.Windows;
- using System.Windows.Input;
- using System.Windows.Media;
- using HandyControl.Data;
- using HandyControl.Tools;
- namespace HandyControl.Interactivity;
- /// <summary>
- /// 鼠标拖动行为,该类是反编译微软的System.Windows.Interactivity程序集得到的,并对其做了些扩展
- /// </summary>
- internal class MouseDragElementBehaviorEx : Behavior<FrameworkElement>
- {
- public static readonly DependencyProperty XProperty = DependencyProperty.Register(nameof(X), typeof(double),
- typeof(MouseDragElementBehaviorEx), new PropertyMetadata(double.NaN, OnXChanged));
- public static readonly DependencyProperty YProperty = DependencyProperty.Register(nameof(Y), typeof(double),
- typeof(MouseDragElementBehaviorEx), new PropertyMetadata(double.NaN, OnYChanged));
- public static readonly DependencyProperty ConstrainToParentBoundsProperty =
- DependencyProperty.Register(nameof(ConstrainToParentBounds), typeof(bool),
- typeof(MouseDragElementBehaviorEx), new PropertyMetadata(ValueBoxes.FalseBox, OnConstrainToParentBoundsChanged));
- private Transform _cachedRenderTransform;
- private Point _relativePosition;
- private bool _settingPosition;
- /// <summary>
- /// 是否固定住Y轴
- /// </summary>
- public bool LockY { get; set; }
- /// <summary>
- /// 是否固定住X轴
- /// </summary>
- public bool LockX { get; set; }
- public double X
- {
- get => (double) GetValue(MouseDragElementBehavior.XProperty);
- set => SetValue(MouseDragElementBehavior.XProperty, value);
- }
- public double Y
- {
- get => (double) GetValue(MouseDragElementBehavior.YProperty);
- set => SetValue(MouseDragElementBehavior.YProperty, value);
- }
- public bool ConstrainToParentBounds
- {
- get => (bool) GetValue(MouseDragElementBehavior.ConstrainToParentBoundsProperty);
- set => SetValue(MouseDragElementBehavior.ConstrainToParentBoundsProperty, ValueBoxes.BooleanBox(value));
- }
- private Rect ElementBounds
- {
- get
- {
- var layoutRect = ArithmeticHelper.GetLayoutRect(AssociatedObject);
- return new Rect(new Point(0.0, 0.0), new Size(layoutRect.Width, layoutRect.Height));
- }
- }
- private FrameworkElement ParentElement => AssociatedObject.Parent as FrameworkElement;
- private UIElement RootElement
- {
- get
- {
- DependencyObject reference = AssociatedObject;
- for (var dependencyObject = reference;
- dependencyObject != null;
- dependencyObject = VisualTreeHelper.GetParent(reference))
- reference = dependencyObject;
- return reference as UIElement;
- }
- }
- private Transform RenderTransform
- {
- get
- {
- if (_cachedRenderTransform == null ||
- !ReferenceEquals(_cachedRenderTransform, AssociatedObject.RenderTransform))
- RenderTransform = CloneTransform(AssociatedObject.RenderTransform);
- return _cachedRenderTransform;
- }
- set
- {
- if (Equals(_cachedRenderTransform, value))
- return;
- _cachedRenderTransform = value;
- AssociatedObject.RenderTransform = value;
- }
- }
- public event MouseEventHandler DragBegun;
- public event MouseEventHandler Dragging;
- public event MouseEventHandler DragFinished;
- private static void OnXChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var dragElementBehavior = (MouseDragElementBehaviorEx) sender;
- dragElementBehavior.UpdatePosition(new Point((double) args.NewValue, dragElementBehavior.Y));
- }
- private static void OnYChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var dragElementBehavior = (MouseDragElementBehaviorEx) sender;
- dragElementBehavior.UpdatePosition(new Point(dragElementBehavior.X, (double) args.NewValue));
- }
- private static void OnConstrainToParentBoundsChanged(object sender, DependencyPropertyChangedEventArgs args)
- {
- var dragElementBehavior = (MouseDragElementBehaviorEx) sender;
- dragElementBehavior.UpdatePosition(new Point(dragElementBehavior.X, dragElementBehavior.Y));
- }
- private void UpdatePosition(Point point)
- {
- if (_settingPosition || AssociatedObject == null)
- return;
- var transformOffset = GetTransformOffset(AssociatedObject.TransformToVisual(RootElement));
- ApplyTranslation(double.IsNaN(point.X) ? 0.0 : point.X - transformOffset.X,
- double.IsNaN(point.Y) ? 0.0 : point.Y - transformOffset.Y);
- }
- private void ApplyTranslation(double x, double y)
- {
- if (ParentElement == null)
- return;
- var point = TransformAsVector(RootElement.TransformToVisual(ParentElement), x, y);
- x = point.X;
- y = point.Y;
- if (ConstrainToParentBounds)
- {
- var parentElement = ParentElement;
- var rect1 = new Rect(0.0, 0.0, parentElement.ActualWidth, parentElement.ActualHeight);
- var rect2 = AssociatedObject.TransformToVisual(parentElement).TransformBounds(ElementBounds);
- rect2.X += x;
- rect2.Y += y;
- if (!RectContainsRect(rect1, rect2))
- {
- if (rect2.X < rect1.Left)
- {
- var num = rect2.X - rect1.Left;
- x -= num;
- }
- else if (rect2.Right > rect1.Right)
- {
- var num = rect2.Right - rect1.Right;
- x -= num;
- }
- if (rect2.Y < rect1.Top)
- {
- var num = rect2.Y - rect1.Top;
- y -= num;
- }
- else if (rect2.Bottom > rect1.Bottom)
- {
- var num = rect2.Bottom - rect1.Bottom;
- y -= num;
- }
- }
- }
- ApplyTranslationTransform(x, y);
- }
- internal void ApplyTranslationTransform(double x, double y)
- {
- var renderTransform = RenderTransform;
- var translateTransform = renderTransform as TranslateTransform;
- if (translateTransform == null)
- {
- var matrixTransform = renderTransform as MatrixTransform;
- if (renderTransform is TransformGroup transformGroup1)
- {
- if (transformGroup1.Children.Count > 0)
- translateTransform =
- transformGroup1.Children[transformGroup1.Children.Count - 1] as TranslateTransform;
- if (translateTransform == null)
- {
- translateTransform = new TranslateTransform();
- transformGroup1.Children.Add(translateTransform);
- }
- }
- else
- {
- if (matrixTransform != null)
- {
- var matrix = matrixTransform.Matrix;
- //在该处对微软的类进行了修改
- if (!LockX)
- {
- matrix.OffsetX += x;
- }
- if (!LockY)
- {
- matrix.OffsetY += y;
- }
- //修改结束
- RenderTransform = new MatrixTransform
- {
- Matrix = matrix
- };
- return;
- }
- var transformGroup2 = new TransformGroup();
- translateTransform = new TranslateTransform();
- if (renderTransform != null)
- transformGroup2.Children.Add(renderTransform);
- transformGroup2.Children.Add(translateTransform);
- RenderTransform = transformGroup2;
- }
- }
- //在该处对微软的类进行了修改
- if (!LockX)
- {
- translateTransform.X += x;
- }
- if (!LockY)
- {
- translateTransform.Y += y;
- }
- //修改结束
- }
- internal static Transform CloneTransform(Transform transform)
- {
- if (transform == null)
- return null;
- if (transform is ScaleTransform scaleTransform)
- return new ScaleTransform
- {
- CenterX = scaleTransform.CenterX,
- CenterY = scaleTransform.CenterY,
- ScaleX = scaleTransform.ScaleX,
- ScaleY = scaleTransform.ScaleY
- };
- if (transform is RotateTransform rotateTransform)
- return new RotateTransform
- {
- Angle = rotateTransform.Angle,
- CenterX = rotateTransform.CenterX,
- CenterY = rotateTransform.CenterY
- };
- if (transform is SkewTransform skewTransform)
- return new SkewTransform
- {
- AngleX = skewTransform.AngleX,
- AngleY = skewTransform.AngleY,
- CenterX = skewTransform.CenterX,
- CenterY = skewTransform.CenterY
- };
- if (transform is TranslateTransform translateTransform)
- return new TranslateTransform
- {
- X = translateTransform.X,
- Y = translateTransform.Y
- };
- if (transform is MatrixTransform matrixTransform)
- return new MatrixTransform
- {
- Matrix = matrixTransform.Matrix
- };
- if (!(transform is TransformGroup transformGroup1))
- return null;
- var transformGroup2 = new TransformGroup();
- foreach (var child in transformGroup1.Children)
- transformGroup2.Children.Add(CloneTransform(child));
- return transformGroup2;
- }
- private void UpdatePosition()
- {
- var transformOffset = GetTransformOffset(AssociatedObject.TransformToVisual(RootElement));
- X = transformOffset.X;
- Y = transformOffset.Y;
- }
- internal void StartDrag(Point positionInElementCoordinates)
- {
- _relativePosition = positionInElementCoordinates;
- AssociatedObject.CaptureMouse();
- AssociatedObject.MouseMove += OnMouseMove;
- AssociatedObject.LostMouseCapture += OnLostMouseCapture;
- AssociatedObject.AddHandler(UIElement.MouseLeftButtonUpEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonUp), false);
- }
- internal void HandleDrag(Point newPositionInElementCoordinates)
- {
- var point = TransformAsVector(AssociatedObject.TransformToVisual(RootElement),
- newPositionInElementCoordinates.X - _relativePosition.X,
- newPositionInElementCoordinates.Y - _relativePosition.Y);
- _settingPosition = true;
- ApplyTranslation(point.X, point.Y);
- UpdatePosition();
- _settingPosition = false;
- }
- internal void EndDrag()
- {
- AssociatedObject.MouseMove -= OnMouseMove;
- AssociatedObject.LostMouseCapture -= OnLostMouseCapture;
- AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonUpEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonUp));
- }
- private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- StartDrag(e.GetPosition(AssociatedObject));
- DragBegun?.Invoke(this, e);
- }
- private void OnLostMouseCapture(object sender, MouseEventArgs e)
- {
- EndDrag();
- DragFinished?.Invoke(this, e);
- }
- private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- AssociatedObject.ReleaseMouseCapture();
- }
- private void OnMouseMove(object sender, MouseEventArgs e)
- {
- HandleDrag(e.GetPosition(AssociatedObject));
- Dragging?.Invoke(this, e);
- }
- private static bool RectContainsRect(Rect rect1, Rect rect2)
- {
- if (rect1.IsEmpty || rect2.IsEmpty || rect1.X > rect2.X || rect1.Y > rect2.Y ||
- rect1.X + rect1.Width < rect2.X + rect2.Width)
- return false;
- return rect1.Y + rect1.Height >= rect2.Y + rect2.Height;
- }
- private static Point TransformAsVector(GeneralTransform transform, double x, double y)
- {
- var point1 = transform.Transform(new Point(0.0, 0.0));
- var point2 = transform.Transform(new Point(x, y));
- return new Point(point2.X - point1.X, point2.Y - point1.Y);
- }
- private static Point GetTransformOffset(GeneralTransform transform)
- {
- return transform.Transform(new Point(0.0, 0.0));
- }
- protected override void OnAttached()
- {
- AssociatedObject.AddHandler(UIElement.MouseLeftButtonDownEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonDown), false);
- }
- protected override void OnDetaching()
- {
- AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonDownEvent,
- new MouseButtonEventHandler(OnMouseLeftButtonDown));
- }
- }
|