WPF 拖动实现

在WPF中实现控件的拖动很多是是用thumb控件,今天学习到了一种新的方式,采用Behavior  实现了控件的拖动及位置限制

效果展示

 

 

代码如下

    /// <summary>
    /// 拖动辅助类
    /// </summary>
    public class DragMoveBehavior : Behavior<FrameworkElement>
    {
        #region Property   

        public static readonly DependencyProperty MaxHProperty = DependencyProperty.Register("MaxH", typeof(double), typeof(DragMoveBehavior), new PropertyMetadata(0d, OnMaxHChanged));

        public static readonly DependencyProperty MaxWProperty = DependencyProperty.Register("MaxW", typeof(double), typeof(DragMoveBehavior), new PropertyMetadata(0d, OnMaxWChanged));
        /// <summary>
        /// max w
        /// </summary>
        public double MaxW
        {
            get { return (double)GetValue(MaxWProperty); }
            set { SetValue(MaxWProperty, value); }
        }
        /// <summary>
        /// max h
        /// </summary>
        public double MaxH
        {

            get { return (double)GetValue(MaxHProperty); }
            set { SetValue(MaxHProperty, value); }

        }
        public double H
        {
            get { return AssociatedObject.Height; }
        }
        public double W
        {
            get { return AssociatedObject.Width; }
        }
        private Transform RenderTransform
        {
            get { return AssociatedObject.RenderTransform; }
            set
            {
                AssociatedObject.RenderTransform = value;
            }
        }

        private Point _mousePoint;

        #endregion

        private static void OnMaxHChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (DragMoveBehavior)d;
            behavior.MaxH = (double)e.NewValue;
        }
        private static void OnMaxWChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (DragMoveBehavior)d;
            behavior.MaxW = (double)e.NewValue;
        }
        protected override void OnAttached()
        {
            AssociatedObject.AddHandler(UIElement.MouseLeftButtonDownEvent,
                new MouseButtonEventHandler(OnMouseLeftButtonDown), false);
            UpdatePosition(new Point(RenderTransform.Value.OffsetX, RenderTransform.Value.OffsetY));
        }

        protected override void OnDetaching()
        {
            AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonDownEvent,
                new MouseButtonEventHandler(OnMouseLeftButtonDown));
        }

        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _mousePoint = e.GetPosition(null);
            AssociatedObject.CaptureMouse();
            AssociatedObject.MouseMove += OnMouseMove;
            AssociatedObject.LostMouseCapture += OnLostMouseCapture;
            AssociatedObject.AddHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnMouseLeftButtonUp), false);
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            //移动鼠标后新的位置
            var newPoint = e.GetPosition(null);

            //本次移动的偏移量
            var offset = newPoint - _mousePoint;

            //保存当前鼠标位置
            _mousePoint = newPoint;

            //更新位置
            ApplyTranslation(RenderTransform.Value.OffsetX + offset.X, RenderTransform.Value.OffsetY + offset.Y);

        }

        private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            AssociatedObject.ReleaseMouseCapture();
        }

        private void OnLostMouseCapture(object sender, MouseEventArgs e)
        {
            AssociatedObject.MouseMove -= OnMouseMove;
            AssociatedObject.LostMouseCapture -= OnLostMouseCapture;
            AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnMouseLeftButtonUp));
        }

        /// <summary>
        /// 尝试更新位置
        /// </summary>
        /// <param name="point"></param>
        private void UpdatePosition(Point point)
        {
            if (AssociatedObject == null)
                return;
            ApplyTranslation(point.X, point.Y);
        }

        /// <summary>
        /// 更新平移转换
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void ApplyTranslation(double x, double y)
        {
            var transfromGroup = RenderTransform as TransformGroup;
            if (transfromGroup == null || transfromGroup.Children.FirstOrDefault(o =>
                  (o.GetType() == typeof(TranslateTransform))
             ) == default(TranslateTransform))
            {
                var rt = new TransformGroup
                {
                    Children = new TransformCollection()
                    {
                        new TranslateTransform(x, y)
                    }
                };
                return;
            }

            if (x < 0)
            {
                x = 0;
            }
            else if (x > MaxW - W)
            {
                x = MaxW - W;
            }
            if (y < 0)
            {
                y = 0;
            }
            else if (y > MaxH - H)
            {
                y = MaxH - H;
            }
            TranslateTransform translateTransform = (TranslateTransform)transfromGroup.Children.First(o => o.GetType() == typeof(TranslateTransform));
            translateTransform.X = x;
            translateTransform.Y = y;
        }
    }
后台代码辅助类

页面设置代码如下

<Window x:Class="DragMoveDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:behavior="clr-namespace:DragMoveDemo"
        Title="MainWindow" Height="450" Width="625">
    <Canvas Height="330" Width="525" Background="Yellow">
        <TextBox x:Name="xpoint" Canvas.Left="35" Canvas.Top="-32" Width="85" Text="34"></TextBox>
        <TextBox x:Name="ypoint" Canvas.Left="305" Canvas.Top="-32" Width="75"  Text="44" RenderTransformOrigin="1,0.412"></TextBox>
        <Rectangle Width="90" Height="80" Fill="Red" RenderTransformOrigin="0.5,0.5">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform X="{Binding ElementName=xpoint, Path=Text,Mode=TwoWay}"
                                        Y="{Binding ElementName=ypoint,Path=Text,Mode=TwoWay}"/>
                </TransformGroup>
            </Rectangle.RenderTransform>
            <i:Interaction.Behaviors>
                <behavior:DragMoveBehavior  MaxH="330" MaxW="525" />
            </i:Interaction.Behaviors>
        </Rectangle>
    </Canvas>

</Window>
前台使用试例

 

posted @ 2021-05-12 09:41  dovese  阅读(187)  评论(0编辑  收藏  举报