(一)textbox控件在布局中放大缩小和移动位置

文章介绍了如何在WPF中为控件添加动态缩放和拖动功能,通过在控件周围添加Thumb并处理DragDelta事件来实现。关键步骤包括创建和布局Thumb,以及编写拖动逻辑来调整控件尺寸。示例代码展示了一个自定义TextBox控件的实现,并提供了添加和绑定事件的方法。
摘要由CSDN通过智能技术生成

写在前面

前奏:笔者在最近上班过程中,突遇同事遇到图片放控件中放大缩小的问题,本来自己也是处于忙碌状态之中,奈何架不住一包华子的诱惑,就去翻看了之前写过的关于控件动态添加和改变的项目,写了有一段时间了,把代码发给了他,顺带自己也做个总结

难点分析

首先,要想实现功能就得知道具体要完成的是什么,对于这个控件可移动,光靠控件本身肯定是不行的,必须对控件进行改造,或者给控件加点东西,在这里我选择了使用第二种方法,也就是给控件加点东西,给他外面套一个Grid或者其他的容器,控件的四周加上可以托拉拽的Thumb,如图所示
请添加图片描述
矩形为控件本身,我们要做的事在他的四周安插"眼线",以便随时都能控制控件的大小(画的有些丑勿介意)

关键就是画thumb以及定义thumb的dragdelta事件,这里时使用Grid作为容器,一般情况大家都会习惯使用Canvas控件,直接上这个类的代码,主要就是他的初始化方法和拖动逻辑

    public class GridAdorner : Adorner
    {
        //4条边
        Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
        //4个角
        Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
        //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
        public Grid _grid;
        UIElement _adornedElement;
        public GridAdorner(UIElement adornedElement) : base(adornedElement)
        {
            哪些需要隐藏thumb
            //bool disappear = false;
            //if(adornedElement.GetType() == typeof(Border))
            //{
            //    disappear = true;
            //}

            _adornedElement = adornedElement;
            //初始化thumb
            _leftThumb = new Thumb();
            _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftThumb.VerticalAlignment = VerticalAlignment.Center;
            _leftThumb.Cursor = Cursors.SizeWE;
            _topThumb = new Thumb();
            _topThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _topThumb.VerticalAlignment = VerticalAlignment.Top;
            _topThumb.Cursor = Cursors.SizeNS;
            _rightThumb = new Thumb();
            _rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightThumb.VerticalAlignment = VerticalAlignment.Center;
            _rightThumb.Cursor = Cursors.SizeWE;
            _bottomThumb = new Thumb();
            _bottomThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _bottomThumb.Cursor = Cursors.SizeNS;
            _lefTopThumb = new Thumb();
            _lefTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _lefTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _lefTopThumb.Cursor = Cursors.SizeNWSE;
            _rightTopThumb = new Thumb();
            _rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _rightTopThumb.Cursor = Cursors.SizeNESW;
            _rightBottomThumb = new Thumb();
            _rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _rightBottomThumb.Cursor = Cursors.SizeNWSE;
            _leftbottomThumb = new Thumb();
            _leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _leftbottomThumb.Cursor = Cursors.SizeNESW;
            _grid = new Grid();
            _grid.Children.Add(_leftThumb);
            _grid.Children.Add(_topThumb);
            _grid.Children.Add(_rightThumb);
            _grid.Children.Add(_bottomThumb);
            _grid.Children.Add(_lefTopThumb);
            _grid.Children.Add(_rightTopThumb);
            _grid.Children.Add(_rightBottomThumb);
            _grid.Children.Add(_leftbottomThumb);
            AddVisualChild(_grid);
            foreach (Thumb thumb in _grid.Children)
            {
                //if (disappear == true)
                //    thumb.Visibility = Visibility.Collapsed;
                thumb.Width = 8;//16
                thumb.Height = 8;//16
                thumb.Background = Brushes.Green;
                thumb.Template = new ControlTemplate(typeof(Thumb))
                {
                    VisualTree = GetFactory(new SolidColorBrush(Colors.White))
                };
                thumb.DragDelta += Thumb_DragDelta;
            }
        }
        protected override Visual GetVisualChild(int index)
        {
            return _grid;
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return 1;
            }
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            //直接给grid布局,grid内部的thumb会自动布局。
            _grid.Arrange(new Rect(new Point(-_leftThumb.Width / 2, -_leftThumb.Height / 2), new Size(finalSize.Width + _leftThumb.Width, finalSize.Height + _leftThumb.Height)));
            return finalSize;
        }
        //拖动逻辑
        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var c = _adornedElement as FrameworkElement;
            var thumb = sender as FrameworkElement;
            var HorizonLocation = c.HorizontalAlignment;
            var VerticaLocation = c.VerticalAlignment;
            double left, top, right, bottom, width, height;
            if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
            {
                right = c.Margin.Right;
                left = c.Margin.Left + e.HorizontalChange;
                width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) - e.HorizontalChange;
            }
            else
            {
                left = c.Margin.Left;
                right = c.Margin.Right - e.HorizontalChange;
                width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) + e.HorizontalChange;
            }

            if (thumb.VerticalAlignment == VerticalAlignment.Top)
            {
                bottom = c.Margin.Bottom;
                top = c.Margin.Top + e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) - e.VerticalChange;

            }
            else
            {
                top = c.Margin.Top;
                bottom = c.Margin.Bottom - e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) + e.VerticalChange;
            }
            if (thumb.HorizontalAlignment != HorizontalAlignment.Center)
            {
                if (width >= 0)
                {
                    c.Margin = new Thickness(left, c.Margin.Top, right, c.Margin.Bottom);
                    c.Width = width;
                }
            }
            if (thumb.VerticalAlignment != VerticalAlignment.Center)
            {
                if (height >= 0)
                {
                    c.Margin = new Thickness(c.Margin.Left, top, c.Margin.Right, bottom);
                    c.Height = height;
                }
            }
            c.HorizontalAlignment = HorizonLocation;
            c.VerticalAlignment = VerticaLocation;
        }
        //thumb的样式
        FrameworkElementFactory GetFactory(Brush back)
        {
            var fef = new FrameworkElementFactory(typeof(Ellipse));
            fef.SetValue(Ellipse.FillProperty, back);
            fef.SetValue(Ellipse.StrokeProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")));
            fef.SetValue(Ellipse.StrokeThicknessProperty, (double)1);
            return fef;
        }
    }

到这里其实关键的步骤已经解决了,我这里事自定义了textbox控件,也就是自定义一个用户控件,在里面放一个Grid包着的TextBox,使用的时候用这个自定义好的自定义控件

<UserControl x:Class="IQCP.Controls.SelfTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:IQCP.Controls"
             mc:Ignorable="d">
    <Grid>
        <TextBox Name="content"></TextBox>
    </Grid>
</UserControl>

代码中添加这个控件并给控件的相关事件做绑定

  /// <summary>
        /// 添加textbox
        /// </summary>    
        public ICommand AddTextBox=> new DelegateCommand(obj =>
        {
            try
            {
                StartMW start = obj as StartMW;
                SelfTextBox tb = new SelfTextBox();
                tb.content.Text = "模板文本框 内容可改";
                tb.content.BorderThickness = new Thickness(0);
                tb.Height = 40;
                tb.Width = 120;
                tb.Name = "textbox_" + start.content.Children.Count + 1;
                //tb.MouseDown += TextBox_MouseDown;
                //tb.MouseUp += TextBox_MouseUp;
                tb.content.MouseDoubleClick += Tb_MouseDoubleClick;
                tb.PreviewKeyDown += Tb_PreviewKeyDown;
                tb.content.PreviewMouseDown += Tb_PreviewMouseDown;
                tb.content.PreviewMouseUp += Tb_PreviewMouseUp;
                tb.content.MouseMove += TextBox_MouseMove;
                tb.content.GotMouseCapture += tbox_GotMouseCapture;
                tb.content.HorizontalAlignment = HorizontalAlignment.Center;
                tb.content.VerticalAlignment = VerticalAlignment.Center;
                start.content.Children.Add(tb);
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(tb);
                GridAdorner grid = new GridAdorner(tb);
                layer.Add(grid);

            }
            catch (Exception err)
            {
                FileHandler.WriteErrLog(System.Reflection.MethodBase.GetCurrentMethod().Name + "|Errmsg:" + err.Message);
            }
        });

        private void Tb_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                SelfTextBox mdg = sender as SelfTextBox;
                StartMW start = Window.GetWindow(mdg) as StartMW;
                if ((Keyboard.Modifiers == ModifierKeys.Control) && (e.Key == Key.C))
                {
                    SelfTextBox tb = new SelfTextBox();
                    tb.content.Text = "模板文本框 内容可改";
                    tb.content.BorderThickness = new Thickness(0);
                    tb.Height = 40;
                    tb.Width = 120;
                    tb.Name = "textbox_" + start.content.Children.Count + 1;
                    //tb.MouseDown += TextBox_MouseDown;
                    //tb.MouseUp += TextBox_MouseUp;
                    tb.content.MouseDoubleClick += Tb_MouseDoubleClick;
                    tb.PreviewKeyDown += Tb_PreviewKeyDown;
                    tb.content.PreviewMouseDown += Tb_PreviewMouseDown;
                    tb.content.PreviewMouseUp += Tb_PreviewMouseUp;
                    tb.content.MouseMove += TextBox_MouseMove;
                    tb.content.GotMouseCapture += tbox_GotMouseCapture;
                    tb.content.HorizontalAlignment = HorizontalAlignment.Center;
                    tb.content.VerticalAlignment = VerticalAlignment.Center;
                    start.content.Children.Add(tb);
                    AdornerLayer layer = AdornerLayer.GetAdornerLayer(tb);
                    GridAdorner grid = new GridAdorner(tb);
                    layer.Add(grid);
                }

                if (e.Key == Key.Delete)
                {
                    start.content.Children.Remove(mdg);
                }
            }
            catch (Exception err)
            {
                FileHandler.WriteErrLog(System.Reflection.MethodBase.GetCurrentMethod().Name + "|Errmsg:" + err.Message);
            }
          
        }

        private void Tb_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var c = sender as TextBox;
            c.Focusable = true;
            c.SelectionStart = c.Text.Length;
            c.Focus();
        }

        private void Tb_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            var c = sender as TextBox;            
            IsMouseDown = false;
            c.ReleaseMouseCapture();
        }

        private void Tb_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                var c = sender as TextBox;
                var cself = (c.Parent as Grid).Parent as SelfTextBox;
                StartMW swin = Window.GetWindow(c) as StartMW;
                swin.controloprations.Visibility = Visibility.Visible;
                currentname = cself.Name;
                IsMouseDown = true;
                TbmoveCount = 0;
                c.Focusable = false;

                _mouseDownPosition = e.GetPosition(swin);
                var transform = c.RenderTransform as TranslateTransform;
                if (transform == null)
                {
                    transform = new TranslateTransform();
                    c.RenderTransform = transform;
                }

                var TBtransform = cself.RenderTransform as TranslateTransform;
                if (TBtransform == null)
                {
                    TBtransform = new TranslateTransform();
                    cself.RenderTransform = TBtransform;
                }

                _mouseDownControlPosition = new Point(transform.X, transform.Y);
                _mouseDownTBControlPosition = new Point(TBtransform.X, TBtransform.Y);
                c.CaptureMouse();
            }
            catch (Exception err)
            {
                FileHandler.WriteErrLog(System.Reflection.MethodBase.GetCurrentMethod().Name + "|Errmsg:" + err.Message);
            }
        }

        private int TbmoveCount = 0;
        private void TextBox_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                TextBox sb = sender as TextBox;
                var c = (sb.Parent as Grid).Parent as SelfTextBox;
                TbmoveCount++;
                if (IsMouseDown && TbmoveCount >3)
                {
                    TbmoveCount = 0;
                    StartMW swin = Window.GetWindow(c) as StartMW;
                    //移动过程中thumb隐藏
                    AdornerLayer mylayer = AdornerLayer.GetAdornerLayer(c);
                    Adorner[] adorners = mylayer.GetAdorners(c);
                    var gridadorner = adorners.Where(t => t.GetType() == typeof(GridAdorner)).FirstOrDefault() as GridAdorner;
                    if (gridadorner != null)
                    {
                        foreach (Thumb thumb in gridadorner._grid.Children)
                        {
                            thumb.Visibility = Visibility.Collapsed;
                        }
                    }

                    var pos = e.GetPosition(swin);
                    //var dp = pos - _mouseDownPosition;
                    //var transform = sb.RenderTransform as TranslateTransform;
                    //transform.X = _mouseDownControlPosition.X + dp.X;
                    //transform.Y = _mouseDownControlPosition.Y + dp.Y;


                    var tbdp = pos - _mouseDownPosition;
                    var TBtransform = c.RenderTransform as TranslateTransform;
                    TBtransform.X = _mouseDownTBControlPosition.X + tbdp.X;
                    TBtransform.Y = _mouseDownTBControlPosition.Y + tbdp.Y;
                }
            }
            catch (Exception err)
            {
                FileHandler.WriteErrLog(System.Reflection.MethodBase.GetCurrentMethod().Name + "|Errmsg:" + err.Message);
            }
        }

   

        private void tbox_GotMouseCapture(object sender, MouseEventArgs e)
        {
            TextBox sb = sender as TextBox;
            var c = (sb.Parent as Grid).Parent as SelfTextBox;
            //if(c.IsMouseOver)
            //{
            //    StartMW swin = Window.GetWindow(c) as StartMW;
            //    IsMouseDown = true;
            //    _mouseDownPosition = e.GetPosition(swin);
            //    var transform = c.RenderTransform as TranslateTransform;
            //    if (transform == null)
            //    {
            //        transform = new TranslateTransform();
            //        c.RenderTransform = transform;
            //    }
            //    _mouseDownControlPosition = new Point(transform.X, transform.Y);
            //    c.CaptureMouse();
            //}

            //鼠标capture显示thumb
            AdornerLayer mylayer = AdornerLayer.GetAdornerLayer(c);
            Adorner[] adorners = mylayer.GetAdorners(c);
            var gridadorner = adorners.Where(t => t.GetType() == typeof(GridAdorner)).FirstOrDefault() as GridAdorner;
            if (gridadorner != null)
            {
                foreach (Thumb thumb in gridadorner._grid.Children)
                {
                    thumb.Visibility = Visibility.Visible;
                }
            }
        }

OK 到这基本上功能已经是完成了,代码需要自己提取一下,因为我写的是一个demo工程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MasterRyan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值