C# wpf Grid中实现控件拖动调整大小的示例代码

作者:CodeOfCC 时间:2023-05-15 17:12:03 

前言

在《C# wpf Canvas中实现控件动态调整大小》中我们实现了Canvas中的控件动态调整大小,由于Grid也是可层叠布局,在Grid中也是可以实现动态调整大小的。

一、功能说明

8个点方放置在控件的8个方位上,通过拖动这些点对控件进行拉伸或缩小,示意图如下:

C# wpf Grid中实现控件拖动调整大小的示例代码

二、如何实现?

1.继承Adorner

通过装饰器的方式添加8个点在控件上,这样既可以不影响控件布局,又可以自由摆放8点控件。通过重写方法,给装饰添加控件。必要的重写的方法如下面示例所示:

public class GridAdorner : Adorner
{
 //获取装饰器的元素个数
 protected override Visual GetVisualChild(int index);
 //指定装饰器子元素个数
 protected override int VisualChildrenCount{get;}
 //布局,添加的子元素需要手动布局。
 protected override Size ArrangeOverride(Size finalSize);      
}

2.使用Thumb

因为Thumb实现拖动比较容易,有相关事件获取拖动距离。在装饰器中定义8个Thumb,对应8个方位点。
示例代码如下:

//4条边
Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
//4个角
Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;

初始化

public GridAdorner(UIElement adornedElement) : base(adornedElement)
{
    //初始化thumb
    _leftThumb = new Thumb();
    _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
    _leftThumb.VerticalAlignment = VerticalAlignment.Center;
    _leftThumb.Cursor = Cursors.SizeWE;
    //其他略...
}

3.实现拖动逻辑

在Thumb的DragDelta事件可以获取拖动距离,根据八个方位的不同计算并修改控件的大小。

private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
//1.右侧点HorizontalChange加宽,右边距减HorizontalChange
//2.左侧点HorizontalChange减宽,左边距加HorizontalChange
//3.下侧点VerticalChange加高,下边距减VerticalChange
//4.上侧点VerticalChange减高,上边距加VerticalChange
}

三、完整代码

代码如下:

public class GridAdorner : Adorner
   {
       //4条边
       Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
       //4个角
       Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
       //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
       Grid _grid;
       UIElement _adornedElement;
       public GridAdorner(UIElement adornedElement) : base(adornedElement)
       {
           _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)
           {
               thumb.Width = 16;
               thumb.Height = 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;
           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;
               }
           }
       }
       //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)2);
           return fef;
       }
   }

四、使用示例

示例代码如下:

xml

<Grid>
   <Border  x:Name="border"  Width="200" Height="200"  Background="Gray" ></Border>
</Grid>

在窗口或控件的Loaded事件中添加装饰器:
cs

private void window_Loaded(object sender, RoutedEventArgs e)
{
   var layer = AdornerLayer.GetAdornerLayer(border);
   layer.Add(new GridAdorner(border));
}

效果预览:

C# wpf Grid中实现控件拖动调整大小的示例代码

来源:https://blog.csdn.net/u013113678/article/details/121491198

标签:C#,wpf,Grid,拖动
0
投稿

猜你喜欢

  • 如何通过JVM角度谈谈Java的clone操作

    2023-10-13 09:54:40
  • Java多线程通信wait()和notify()代码实例

    2022-09-27 12:12:11
  • Java中的逻辑控制语句详解

    2023-01-14 09:02:57
  • C#实现移除字符串末尾指定字符的方法

    2023-02-09 13:32:21
  • java操作solr实现查询功能的实例

    2023-08-04 10:41:34
  • 完整的医院就诊挂号系统基于Spring MVC + Spring + MyBatis实现

    2022-06-03 18:07:05
  • Android应用退出登录的实现方法

    2023-11-15 19:52:44
  • linux操作系统安装MONO执行C#程序的详解步骤

    2022-10-04 18:20:04
  • Java基础之this关键字的使用

    2021-05-31 13:12:55
  • Kotlin使用协程实现高效并发程序流程详解

    2021-12-27 20:47:21
  • C# 进行图片压缩的示例代码(对jpg压缩效果最好)

    2023-05-11 16:34:19
  • C#遍历得到checkboxlist选中值和设置选中项的代码

    2022-10-25 20:52:22
  • Android Studio和阿里云数据库实现一个远程聊天程序

    2023-06-14 21:09:16
  • unity实现翻页按钮功能

    2021-07-15 03:33:47
  • Java 判断字符串中是否包含中文的实例详解

    2023-11-06 13:17:18
  • springboot项目配置多个kafka的示例代码

    2023-11-23 23:15:29
  • Java8 使用 stream().sorted()对List集合进行排序的操作

    2022-11-23 20:57:11
  • Java 线程池ThreadPoolExecutor源码解析

    2022-06-28 09:13:59
  • C# Winform使用扩展方法实现自定义富文本框(RichTextBox)字体颜色

    2021-06-23 15:05:50
  • 完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题

    2023-07-03 11:27:25
  • asp之家 软件编程 m.aspxhome.com