Fork me on GitHub

WPF控件拖动

支持任意方向拖动/水平方向拖动/垂直方向拖动

 

 public enum DragDirection
    {
        [Description("任意")]
        Any,
        [Description("水平")]
        Horizontal,
        [Description("垂直")]
        Vertical,
    }

 public class ControlDragExtends : DependencyObject
    {
        public static int GetMaxX(DependencyObject obj)
        {
            return (int)obj.GetValue(MaxXProperty);
        }
        public static void SetMaxX(DependencyObject obj, int value)
        {
            obj.SetValue(MaxXProperty, value);
        }
        public static int GetMaxY(DependencyObject obj)
        {
            return (int)obj.GetValue(MaxYProperty);
        }
        public static void SetMaxY(DependencyObject obj, int value)
        {
            obj.SetValue(MaxYProperty, value);
        }

        public static int GetMinX(DependencyObject obj)
        {
            return (int)obj.GetValue(MinXProperty);
        }
        public static void SetMinX(DependencyObject obj, int value)
        {
            obj.SetValue(MinXProperty, value);
        }
        public static int GetMinY(DependencyObject obj)
        {
            return (int)obj.GetValue(MinYProperty);
        }
        public static void SetMinY(DependencyObject obj, int value)
        {
            obj.SetValue(MinYProperty, value);
        }


        public static DragDirection GetDragDirection(DependencyObject obj)
        {
            return (DragDirection)obj.GetValue(DragDirectionProperty);
        }
        public static void SetDragDirection(DependencyObject obj, DragDirection value)
        {
            obj.SetValue(DragDirectionProperty, value);
        }
        public static bool GetEnableDragMove(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnableDragMoveProperty);
        }
        public static void SetEnableDragMove(DependencyObject obj, bool value)
        {
            obj.SetValue(EnableDragMoveProperty, value);
        }


        // Using a DependencyProperty as the backing store for DragDirection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxYProperty =
            DependencyProperty.Register("MaxY", typeof(int), typeof(ControlDragExtends), new PropertyMetadata(int.MaxValue));
        // Using a DependencyProperty as the backing store for DragDirection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxXProperty =
            DependencyProperty.Register("MaxX", typeof(int), typeof(ControlDragExtends), new PropertyMetadata(int.MaxValue));

        // Using a DependencyProperty as the backing store for DragDirection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinYProperty =
            DependencyProperty.Register("MinY", typeof(int), typeof(ControlDragExtends), new PropertyMetadata(0));
        // Using a DependencyProperty as the backing store for DragDirection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinXProperty =
            DependencyProperty.Register("MinX", typeof(int), typeof(ControlDragExtends), new PropertyMetadata(0));

        // Using a DependencyProperty as the backing store for DragDirection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DragDirectionProperty =
            DependencyProperty.Register("DragDirection", typeof(DragDirection), typeof(ControlDragExtends), new PropertyMetadata(DragDirection.Any));



        /// <summary>
        /// 回车/空格
        /// </summary>
        public static readonly DependencyProperty EnableDragMoveProperty =
            DependencyProperty.RegisterAttached("EnableDragMove", typeof(bool), typeof(ControlDragExtends), new PropertyMetadata(false
                , OnEnableDragMove));

        private static void OnEnableDragMove(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
            {
                var element = d as FrameworkElement;
                if (element == null) return;
                if ((bool)e.NewValue)
                {
                    element.PreviewMouseDown += Element_PreviewMouseDown;
                    element.PreviewMouseMove += Element_PreviewMouseMove;
                    element.PreviewMouseUp += Element_PreviewMouseUp;
                }
            }
        }

        private static void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var c = sender as Control;
            _isMouseDown = true;
            _mouseDownPosition = e.GetPosition(null);
            Console.WriteLine(_mouseDownPosition);
            var transform = c.RenderTransform as TranslateTransform;
            if (transform == null)
            {
                transform = new TranslateTransform();
                c.RenderTransform = transform;
            }
            _mouseDownControlPosition = new Point(transform.X, transform.Y);
            c.CaptureMouse();
        }

        //鼠标是否按下
        static bool _isMouseDown = false;
        //鼠标按下的位置
        static Point _mouseDownPosition;
        //鼠标按下控件的位置
        static Point _mouseDownControlPosition;

        private static void Element_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (_isMouseDown)
            {
                var element = sender as FrameworkElement;
                if (element == null) return;
               
                var transform = element.RenderTransform as TranslateTransform;
                if (transform == null) return;

                var pos = e.GetPosition(null);
                var dp = pos - _mouseDownPosition;

                var newX = _mouseDownControlPosition.X + dp.X;
                var newY = _mouseDownControlPosition.Y + dp.Y;
                switch (GetDragDirection(element))
                {
                    case DragDirection.Horizontal:
                        newX = Math.Max(GetMinX(element), newX);
                        newX = Math.Min(GetMaxX(element), newX);
                        newY = transform.Y;
                        break;
                    case DragDirection.Vertical:
                        newY = Math.Max(GetMinY(element), newY);
                        newY = Math.Min(GetMaxY(element), newY);
                        newX = transform.X;
                        break;
                    case DragDirection.Any:
                    default:
                        break;
                }
                transform.X = newX;
                transform.Y = newY;
            }
        }




        private static void Element_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            var c = sender as Control;
            _isMouseDown = false;
            c.ReleaseMouseCapture();
        }

    }

  使用

<Grid>
        <Button HorizontalAlignment="Left" Margin="20" Content="拖动我" Width="100" Height="45"  local:ControlDragExtends.EnableDragMove="True"  ></Button>

        <Button  x:Name="ButtonTest" local:ControlDragExtends.EnableDragMove="True" local:ControlDragExtends.DragDirection="Vertical" local:ControlDragExtends.MaxY="100" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20,20" Content="附加拖动" Width="100" Height="45"   ></Button>
        <Button  x:Name="ButtonTestMaxX" local:ControlDragExtends.EnableDragMove="True" local:ControlDragExtends.DragDirection="Horizontal" local:ControlDragExtends.MaxX="500" local:ControlDragExtends.MinX="-1000" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="20,20" Content="附加拖动" Width="100" Height="45"   ></Button>
       
    </Grid>

  

 

 

 

效果

 

posted @ 2022-03-18 12:28  黄高林  阅读(525)  评论(0编辑  收藏  举报