废话不多直接上菜
代码语言:javascript复制 /*
注意:只要不带焦点的控件包括用户控件 都可以拖动与拖拽大小 【基类中的【公共参数】可以自行修改哦】
使用方法[这是在一个窗体的后台代码]:
//实例化对象
public DragControlsHelper dragControlsHelper = new DragControlsHelper();
//执行以下方法就可以拖拽了[this属于窗体的对象,小范围拖拽可以自建布局容器]
dragControlsHelper.Insert(控件的对象或者控件的Name, this);
//移除拖拽大小与移动也很简单
dragControlsHelper.Remove(控件的对象或者控件的Name);
//WPF中布局容器有6种如下:
[Grid]网格布局,其中控件或容器需指定位置;
[StackPanel]堆叠面板,其中的控件水平布局、竖直布局;
[DockPanel]停靠面板,内部控件或容器可以放置在上、下、左、右;
[WrapPanel]可以看作是具有自动换行功能的StackPanel容器。窗体太小时,其末尾的控件会自动换行,像Java中的流布局;
[Canvas]坐标布局,基于坐标的布局,利用Canvas.Left,Canvas.Top,Canvas.Right,Canvas.Bottom这四个附加属性来定位控件坐标;
[UniformGrid]指定行和列的数量, 均分有限的容器空间。
//by:Shunnet.top 2022/5/18
*/ /// <summary>
/// 控件拖动基类
/// </summary>
public class DragControlsBase : Adorner
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="Controls">要拖动的控件</param>
/// <param name="LlayoutContainer">窗体的布局容器</param>
public DragControlsBase(UIElement Controls, FrameworkElement LlayoutContainer) : base(Controls)
{
this.Controls = Controls;
this.LlayoutContainer = LlayoutContainer;
InitDragDelta(); //初始化拖动大小
InitMove(); //初始化移动
}
/// <summary>
/// 容器边框颜色
/// </summary>
public SolidColorBrush BorderColor = new SolidColorBrush(Colors.Green);
/// <summary>
/// 容器边框线径
/// </summary>
public Thickness BorderWireDiameter = new Thickness(1);
/// <summary>
/// 容器边框透明度
/// </summary>
public double BorderOpacity = 0;
/// <summary>
/// 拖拽装饰器的内圈颜色
/// </summary>
public SolidColorBrush ThumbInnerColor = new SolidColorBrush(Colors.Red);
/// <summary>
/// 拖拽装饰器的外圈颜色
/// </summary>
public SolidColorBrush ThumbOuterColor = new SolidColorBrush(Colors.Red);
/// <summary>
/// 装饰器线径
/// </summary>
public double ThumbWireDiameter = 1;
/// <summary>
/// 装饰器透明度
/// </summary>
public double ThumbOpacity = 0.6;
/// <summary>
/// 拖拽最小的宽
/// </summary>
public double MinWidth = 100;
/// <summary>
/// 拖拽最小的高
/// </summary>
public double MinHeight = 100;
/// <summary>
/// 拖拽最大的宽
/// </summary>
public double MaxWidth = 500;
/// <summary>
/// 拖拽最大的高
/// </summary>
public double MaxHeight = 500;
#region 私有字段
/// <summary>
/// 4条边
/// </summary>
Thumb LeftThumb, TopThumb, RightThumb, BottomThumb;
/// <summary>
/// 4个角
/// </summary>
Thumb LefTopThumb, RightTopThumb, RightBottomThumb, LeftbottomThumb;
/// <summary>
/// 中间 目前暂不使用
/// </summary>
Thumb CentreThumb;
/// <summary>
/// 布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
/// </summary>
Grid Llayout;
/// <summary>
/// 要拖动的控件
/// </summary>
UIElement Controls;
/// <summary>
/// 窗体的布局容器
/// </summary>
FrameworkElement LlayoutContainer;
/// <summary>
/// 鼠标是否按下
/// </summary>
bool IsMouseDown = false;
/// <summary>
/// 鼠标按下的位置
/// </summary>
Point MouseDownPosition;
/// <summary>
/// 鼠标按下控件的Margin
/// </summary>
Thickness MouseDownMargin;
#endregion
#region 重写方法
protected override Visual GetVisualChild(int index)
{
return Llayout;
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
protected override Size ArrangeOverride(Size finalSize)
{
//直接给容器布局,容器内部的装饰器会自动布局。
Llayout.Arrange(new Rect(new Point(-LeftThumb.Width / 2, -LeftThumb.Height / 2), new Size(finalSize.Width LeftThumb.Width, finalSize.Height LeftThumb.Height)));
return finalSize;
}
#endregion
#region 方法
/// <summary>
/// 初始化拖拽大小
/// </summary>
public void InitDragDelta()
{
//初始化装饰器
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;
CentreThumb = new Thumb();
CentreThumb.HorizontalAlignment = HorizontalAlignment.Center;
CentreThumb.VerticalAlignment = VerticalAlignment.Center;
CentreThumb.Cursor = Cursors.SizeAll;
Llayout = new Grid();
//给布局容器加个边框
Border border = new Border();
border.Margin = new Thickness(2);
border.Opacity = BorderOpacity;
border.BorderThickness = BorderWireDiameter;
border.BorderBrush = BorderColor;
Llayout.Children.Add(border);
//给布局容器添加拖动大小装饰器
Llayout.Children.Add(LeftThumb);
Llayout.Children.Add(TopThumb);
Llayout.Children.Add(RightThumb);
Llayout.Children.Add(BottomThumb);
Llayout.Children.Add(LefTopThumb);
Llayout.Children.Add(RightTopThumb);
Llayout.Children.Add(RightBottomThumb);
Llayout.Children.Add(LeftbottomThumb);
//Llayout.Children.Add(CentreThumb); //中间的装饰器 暂不使用
AddVisualChild(Llayout);
foreach (var item in Llayout.Children)
{
if (item.GetType().Equals(typeof(Thumb)))
{
Thumb thumb = item as Thumb;
thumb.Width = 5; //设置圆圈的宽
thumb.Height = 5; //设置圆圈的高
thumb.Opacity = ThumbOpacity;//透明度
thumb.Template = new ControlTemplate(typeof(Thumb)) //模板
{
VisualTree = GetFactory(ThumbInnerColor, ThumbOuterColor, ThumbWireDiameter)
};
thumb.DragDelta = Control_DragDelta;
}
}
}
/// <summary>
/// 装饰器样式
/// </summary>
/// <param name="InnerColor">内圈颜色</param>
/// <param name="OuterColor">外圈颜色</param>
/// <param name="WireDiameter">线径</param>
/// <param name="Opacity">透明度</param>
/// <returns></returns>
FrameworkElementFactory GetFactory(Brush InnerColor, Brush OuterColor, double WireDiameter)
{
FrameworkElementFactory Element = new FrameworkElementFactory(typeof(Ellipse)); //绘制椭圆形元素
Element.SetValue(Ellipse.FillProperty, InnerColor); //内圈色
Element.SetValue(Ellipse.StrokeProperty, OuterColor); //外圈色
Element.SetValue(Ellipse.StrokeThicknessProperty, WireDiameter); //线径
return Element;
}
/// <summary>
/// 初始化移动
/// </summary>
public void InitMove()
{
//添加移动事件
Controls.MouseLeftButtonDown = Control_MouseLeftButtonDown; //鼠标左键按下
Controls.MouseLeftButtonUp = Control_MouseLeftButtonUp; //鼠标左键松开
Controls.MouseMove = Control_MouseMove; //鼠标移动
}
#endregion
#region 事件
//拖拽大小逻辑
private void Control_DragDelta(object sender, DragDeltaEventArgs e)
{
FrameworkElement Control = Controls as FrameworkElement; //要拖动的控件
FrameworkElement Thumb = sender as FrameworkElement; //哪个装饰被拖动
double Left, Top, Right, Bottom, Width, Height; //左,上,右,下,宽,高
if (Thumb.HorizontalAlignment == HorizontalAlignment.Left)
{
Right = Control.Margin.Right;
Left = Control.Margin.Left e.HorizontalChange;
Width = (double.IsNaN(Control.Width) ? Control.ActualWidth : Control.Width) - e.HorizontalChange;
}
else
{
Left = Control.Margin.Left;
Right = Control.Margin.Right - e.HorizontalChange;
Width = (double.IsNaN(Control.Width) ? Control.ActualWidth : Control.Width) e.HorizontalChange;
}
if (Thumb.VerticalAlignment == VerticalAlignment.Top)
{
Bottom = Control.Margin.Bottom;
Top = Control.Margin.Top e.VerticalChange;
Height = (double.IsNaN(Control.Height) ? Control.ActualHeight : Control.Height) - e.VerticalChange;
}
else
{
Top = Control.Margin.Top;
Bottom = Control.Margin.Bottom - e.VerticalChange;
Height = (double.IsNaN(Control.Height) ? Control.ActualHeight : Control.Height) e.VerticalChange;
}
if (Thumb.HorizontalAlignment != HorizontalAlignment.Center)
{
if (Width >= 0)
{
if (Width >= MinWidth && Width <= MaxWidth)
{
Control.Margin = new Thickness(Left, Control.Margin.Top, Right, Control.Margin.Bottom);
Control.Width = Width;
}
}
}
if (Thumb.VerticalAlignment != VerticalAlignment.Center)
{
if (Height >= 0)
{
if (Height >= MinHeight && Height <= MaxHeight)
{
Control.Margin = new Thickness(Control.Margin.Left, Top, Control.Margin.Right, Bottom);
Control.Height = Height;
}
}
}
}
//鼠标左键按下
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var c = sender as FrameworkElement;
IsMouseDown = true;
MouseDownPosition = e.GetPosition(LlayoutContainer);
MouseDownMargin = c.Margin;
c.CaptureMouse();
}
//鼠标左键松开
private void Control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var c = sender as FrameworkElement;
IsMouseDown = false;
c.ReleaseMouseCapture();
}
//鼠标移动
private void Control_MouseMove(object sender, MouseEventArgs e)
{
if (IsMouseDown)
{
var c = sender as FrameworkElement;
var pos = e.GetPosition(LlayoutContainer);
var dp = pos - MouseDownPosition;
double Left, Top, Right, Bottom; //设置控件坐标
Left = MouseDownMargin.Left dp.X;
Top = MouseDownMargin.Top dp.Y;
Right = MouseDownMargin.Right - dp.X;
Bottom = MouseDownMargin.Bottom - dp.Y;
c.Margin = new Thickness(Left, Top, Right, Bottom);
//GeneralTransform generalTransform = c.TransformToAncestor(LlayoutContainer);
//Point point = generalTransform.Transform(new Point(0, 0));
////控件的 左上右下
//double ControlLeft = c.Margin.Left; //左
//double ControlTop = c.Margin.Top; //上
//double ControlRight = point.X c.Width; //右
//double ControlBottom = point.Y c.Height; //下
}
}
#endregion
}
/// <summary>
/// 控件拖动实现类
/// </summary>
public class DragControlsHelper
{
/// <summary>
/// 数据字典
/// UIElement:要拖动的控件
/// AdornerLayer:装饰器
/// DragControlsBase:装饰器实现类
/// </summary>
Dictionary<UIElement, Tuple<AdornerLayer, DragControlsBase>> DictionaryDataList = new Dictionary<UIElement, Tuple<AdornerLayer, DragControlsBase>>();
/// <summary>
/// 添加项
/// </summary>
/// <param name="Controls">控件</param>
/// <param name="LlayoutContainer">窗体的布局容器:意思就是这个控件是被谁包这的就传它,我一般传窗体对象,窗体包着所有的控件,小范围拖动,自行建布局容器包着要拖动的控件 </param>
public void Insert(UIElement Controls, FrameworkElement LlayoutContainer)
{
if (!DictionaryDataList.ContainsKey(Controls))
{
DragControlsBase dragControlsBase = new DragControlsBase(Controls, LlayoutContainer);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(Controls);
adornerLayer.Add(dragControlsBase);
Tuple<AdornerLayer, DragControlsBase> tuple = new Tuple<AdornerLayer, DragControlsBase>(adornerLayer, dragControlsBase);
DictionaryDataList.Add(Controls, tuple);
}
}
/// <summary>
/// 移除拖动
/// </summary>
/// <param name="Controls">控件</param>
public void Remove(UIElement Controls)
{
if (DictionaryDataList.ContainsKey(Controls))
{
DictionaryDataList[Controls].Item1.Remove(DictionaryDataList[Controls].Item2); //移除此项属性
Delete(Controls); //在集合移除此项
}
}
/// <summary>
/// 删除此项
/// </summary>
/// <param name="Controls">控件</param>
private void Delete(UIElement Controls)
{
DictionaryDataList.Remove(Controls); //直接移除
}
}
/*
动画拖动,包含了控件的移动与缩放大小
by:Shunnet.top 2022/5/20
-----------------------------下面是使用方法---------------------------
*/
#region 后端代码
/*
/// <summary>
/// 三合一
/// </summary>
DragControlsAnimate dragControlsAnimate;
public MainWindow()
{
InitializeComponent();
dragControlsAnimate = new DragControlsAnimate(this, Canvas_Pane); //你得定义一个容器传容器对象或者Name
dragControlsAnimate.Insert(ConShow1);
dragControlsAnimate.Insert(ConShow2);
dragControlsAnimate.MessageEvenTrigger = MessageEvenTrigger;
dragControlsAnimate.DragEvenTrigger = DragEvenTrigger;
}
/// <summary>
/// 消息
/// </summary>
/// <param name="Message">消息</param>
/// <param name="element">哪个控件显示的消息</param>
public void MessageEvenTrigger(string Message, FrameworkElement element)
{
Console.WriteLine($"控件Name:{element.Name}->抛出消息:{Message}");
}
/// <summary>
/// 提醒拖拽事件开始了,请传需要拖动的按钮对象
/// </summary>
/// <param name="element">在哪个控件上触发了拖拽</param>
/// <returns>返回已经创建了新的控件对象 - 是否需要拖拽大小</returns>
public (FrameworkElement NewControl, bool IsDragAndDragSize) DragEvenTrigger(FrameworkElement ShowControl)
{
FrameworkElement NewControl = new FrameworkElement();
bool IsDragAndDragSize = false;
switch (ShowControl.Name)
{
case "ConShow1":
NewControl = InitControls(0);
IsDragAndDragSize = false;
break;
case "ConShow2":
NewControl = InitControls(1);
IsDragAndDragSize = true;
break;
}
return (NewControl, IsDragAndDragSize);
}
/// <summary>
/// 创建图标
/// </summary>
/// <param name="dashboardDataMode">图标类型</param>
private DockPanel InitControls(int A)
{
return new DockPanel() { Background = new SolidColorBrush(A == 0 ? Colors.Red : Colors.Blue), Width = 100, Height = 100 };
}
*/
#endregion
#region 前端代码
/*
<Canvas Name="Canvas_Pane" Background="AliceBlue">
<Button Content="Red" Width="90" Height="50" Grid.Column="0" Name="ConShow1"/>
<Button Content="Blue" Width="90" Height="50" VerticalAlignment="Top" Margin="100,0,0,0" Name="ConShow2"/>
</Canvas>
*/
#endregion
/// <summary>
/// 拖拽控件动画
/// </summary>
public class DragControlsAnimate
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="Windows">窗体</param>
/// <param name="LlayoutContainer">容器:让控件在这里面拖动</param>
public DragControlsAnimate(FrameworkElement Windows, Canvas LlayoutContainer)
{
this.Windows = Windows;
this.LlayoutContainer = LlayoutContainer;
Windows.SizeChanged = Windwos_SizeChanged;
}
#region 私有字段
/// <summary>
/// 界面上已经生成的控件,也就是从哪个控件上拖动的集合
/// </summary>
List<FrameworkElement> ShowControlsList = new List<FrameworkElement>();
/// <summary>
/// 窗体
/// </summary>
FrameworkElement Windows;
/// <summary>
/// 容器:让控件在这里面拖动
/// </summary>
Canvas LlayoutContainer;
/// <summary>
/// 鼠标是否按下
/// </summary>
bool IsMouseDown = false;
/// <summary>
/// 实时需要拖动的控件
/// </summary>
FrameworkElement ControlsObj;
/// <summary>
/// 拖拽大小与移动
/// </summary>
DragControlsHelper dragControlsHelper = new DragControlsHelper();
#endregion
#region 方法
/// <summary>
/// 添加拖拽大小与移动
/// </summary>
public void DragSizeInsert(FrameworkElement Controls, FrameworkElement Window)
{
//创建拖动与拖拽大小
dragControlsHelper.Insert(Controls, Window);
}
/// <summary>
/// 移除拖拽大小与移动
/// </summary>
public void DragSizeRemove(FrameworkElement Controls)
{
//创建拖动与拖拽大小
dragControlsHelper.Remove(Controls);
}
/// <summary>
/// 添加需要拖动的组件
/// </summary>
/// <param name="ControlsShow">界面上已经生成的控件</param>
public void Insert(FrameworkElement ControlsShow)
{
if (!ShowControlsList.Contains(ControlsShow)) //不存在则添加
{
InsertEven(ControlsShow);
ShowControlsList.Add(ControlsShow);
}
}
/// <summary>
/// 移除拖动
/// </summary>
/// <param name="ControlsShow">界面上已经生成的控件</param>
public void Remove(FrameworkElement ControlsShow)
{
if (ShowControlsList.Contains(ControlsShow))
{
RemoveEven(ControlsShow);
ShowControlsList.Remove(ControlsShow); //直接移除
}
}
/// <summary>
/// 创建事件
/// </summary>
/// <param name="ControlsShow">界面上已经生成的控件</param>
public void InsertEven(FrameworkElement ControlsShow)
{
//ControlsShow.PreviewMouseLeftButtonDown = delegate (object sender, MouseButtonEventArgs e) { ControlsShow_PreviewMouseLeftButtonDown(sender, e, ControlsObj); };
//ControlsShow.PreviewMouseLeftButtonUp = delegate (object sender, MouseButtonEventArgs e) { ControlsShow_PreviewMouseLeftButtonUp(sender, e, ControlsObj); };
//ControlsShow.PreviewMouseMove = delegate (object sender, MouseEventArgs e) { ControlsShow_PreviewMouseMove(sender, e, ControlsObj); };
ControlsShow.PreviewMouseLeftButtonDown = ControlsShow_PreviewMouseLeftButtonDown;
ControlsShow.PreviewMouseLeftButtonUp = ControlsShow_PreviewMouseLeftButtonUp;
ControlsShow.PreviewMouseMove = ControlsShow_PreviewMouseMove;
}
/// <summary>
/// 移除事件
/// </summary>
/// <param name="ControlsShow">界面上已经生成的控件</param>
public void RemoveEven(FrameworkElement ControlsShow)
{
ControlsShow.PreviewMouseLeftButtonDown -= ControlsShow_PreviewMouseLeftButtonDown;
ControlsShow.PreviewMouseLeftButtonUp -= ControlsShow_PreviewMouseLeftButtonUp;
ControlsShow.PreviewMouseMove -= ControlsShow_PreviewMouseMove;
}
#endregion
#region 委托回调事件
/// <summary>
/// 定义委托 提醒拖拽事件开始了,请传需要拖动的按钮对象
/// </summary>
/// <param name="ShowControl">在哪个控件上触发了拖拽</param>
/// <returns>返回已经创建了新的控件对象 - 是否需要拖拽大小</returns>
public delegate (FrameworkElement NewControl, bool IsDragAndDragSize) dragEvenTrigger(FrameworkElement ShowControl);
/// <summary>
/// 实现委托
/// </summary>
public dragEvenTrigger DragEvenTrigger;
/// <summary>
/// 消息委托
/// </summary>
/// <param name="Message">消息</param>
/// <param name="element">哪个控件显示的消息</param>
public delegate void messageEvenTrigger(string Message, FrameworkElement element);
/// <summary>
/// 实现委托
/// </summary>
public messageEvenTrigger MessageEvenTrigger;
#endregion
#region 执行事件
//移动位置
private void ControlsShow_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (ControlsObj == null) return;
if (IsMouseDown)
{
Point pos = e.GetPosition(Windows);
Canvas.SetLeft(ControlsObj, pos.X - ControlsObj.Width / 2);
Canvas.SetTop(ControlsObj, pos.Y - ControlsObj.Height / 2);
}
}
//当在已显示的控件左键点松开后
private void ControlsShow_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
IsMouseDown = false;
if (ControlsObj == null) return;
ControlsObj.Opacity = 1;
ControlsObj = null;
}
//当在已显示的控件左键点击后
private void ControlsShow_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
(FrameworkElement element, bool IsDragAndDragSize) Data = DragEvenTrigger(sender as FrameworkElement);
ControlsObj = Data.element;
if (!LlayoutContainer.Children.Contains(ControlsObj))
{
IsMouseDown = true;
Point Position = e.GetPosition(Windows);
ControlsObj.Opacity = 0.5;
Canvas.SetLeft(ControlsObj, Position.X - ControlsObj.Width / 2);
Canvas.SetTop(ControlsObj, Position.Y - ControlsObj.Height / 2);
LlayoutContainer.Children.Add(ControlsObj);
if (Data.IsDragAndDragSize)
{
//添加拖拽大小与移动
DragSizeInsert(ControlsObj, Windows);
}
}
else
{
MessageEvenTrigger("此控件已在布局中存在", sender as FrameworkElement);
ControlsObj = null;
}
}
//当窗体大小改变,布局容器也要跟着改变大小
private void Windwos_SizeChanged(object sender, SizeChangedEventArgs e)
{
FrameworkElement window = sender as FrameworkElement;
LlayoutContainer.Width = window.ActualWidth;
LlayoutContainer.Height = window.ActualHeight;
}
#endregion
}
“关注[顺网]微信公众号,了解更多更有趣的实时信息”
本文作者:[博主]大顺
本文链接:https://shunnet.top/YFNBrm
版权声明:转载注明出处,谢谢 ☺