WPF实现鼠标拖动控件并带有中间动效
标签:type div drag int sele sch ora 封装 鼠标移动
一. 前提
要实现鼠标对控件的拖拽移动,首先必须知道下面几点:
-
WPF中的鼠标左键按下、鼠标移动事件,有时候通过XAML界面添加的时候并有没有作用;
-
如果在移动时候要持续修改控件的属性,我们通过改变RenderTransform来修改呈现,而不是直接修改控件本身的属性(会卡);
-
通过 VisualBrush 来填充Rectangle,来实现鼠标拖动控件所形成的影子;
-
通过创建一个带有目标依赖属性的Button的子类,来将有关数据放入Button的子类中;
二. 过程
这里以按钮的拖动,分析一下这个过程:
-
首先在点击按钮(鼠标左键按下),我们以按钮为原型创建一个 “影子” ;
-
在鼠标按住左键拖动的时候,实现对这个 “影子” 的拖动跟随效果;
-
最后,在放开鼠标(鼠标左边抬起)时,将原来的按钮的位置直接移动到抬起时的位置并去除跟随的 “影子”;
三. 代码
这边的代码进行了封装,如过要看没有封装的版本请见示例工程(下面可以下载)
- DragButton 类,继承自 Button 类
public class DragButton : Button
{
public static readonly DependencyProperty IsDragProperty = DependencyProperty.Register("IsDrag", typeof(Boolean), typeof(DragButton));
public static readonly DependencyProperty CurrentPosProperty = DependencyProperty.Register("CurrentPos", typeof(Point), typeof(DragButton));
public static readonly DependencyProperty ClickPosProperty = DependencyProperty.Register("ClickPos", typeof(Point), typeof(DragButton));
///
/// 是否拖拽
///
public bool IsDrag
{
get
{
return (bool)this.GetValue(IsDragProperty);
}
set
{
this.SetValue(IsDragProperty, value);
}
}
///
/// 按钮的定位位置
///
public Point CurrentPos
{
get
{
return (Point)this.GetValue(CurrentPosProperty);
}
set
{
this.SetValue(CurrentPosProperty, value);
}
}
///
/// 当前鼠标点在按钮上的位置
///
public Point ClickPos
{
get
{
return (Point)this.GetValue(ClickPosProperty);
}
set
{
this.SetValue(ClickPosProperty, value);
}
}
}
Window x:Class="Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Demo"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWindow">
Canvas x:Name="canvas" Background="Aqua" Margin="0,0,36,9">
local:DragButton x:Name="btn" Canvas.Left="173" Canvas.Top="64" Width="80" Height="30" Content="拖拽"/>
Canvas>
Window>
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//添加事件
this.btn.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.MouseButtonLeftDown), true);
this.canvas.AddHandler(Canvas.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.CanvasButtonLeftUp), true);
this.canvas.AddHandler(Canvas.MouseMoveEvent, new MouseEventHandler(this.Canvas_MouseMove),true);
this.btn.CurrentPos = new Point((double)this.btn.GetValue(Canvas.LeftProperty), (double)this.btn.GetValue(Canvas.TopProperty));
}
///
/// 区域移动事件
///
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if(this.btn.IsDrag)
{
Point offsetPoint = e.GetPosition(this.canvas);
double xOffset = offsetPoint.X - this.btn.CurrentPos.X - this.btn.ClickPos.X;
double yOffset = offsetPoint.Y - this.btn.CurrentPos.Y - this.btn.ClickPos.Y;
Rectangle rect = LogicalTreeHelper.FindLogicalNode(this, "rect") as Rectangle;
TranslateTransform transform = (TranslateTransform)rect.RenderTransform;
transform.X += xOffset;
transform.Y += yOffset;
this.btn.CurrentPos = new Point(offsetPoint.X- this.btn.ClickPos.X, offsetPoint.Y- this.btn.ClickPos.Y);
}
}
///
/// 鼠标左键按下
///
private void MouseButtonLeftDown(object sender, MouseButtonEventArgs e)
{
if(!this.btn.IsDrag)
{
this.btn.ClickPos = e.GetPosition(this.btn);
VisualBrush visualBrush = new VisualBrush(this.btn);
Rectangle rect = new Rectangle() { Width = this.btn.ActualWidth, Height = this.btn.Height, Fill = visualBrush, Name = "rect" };
rect.SetValue(Canvas.LeftProperty, this.btn.GetValue(Canvas.LeftProperty));
rect.SetValue(Canvas.TopProperty, this.btn.GetValue(Canvas.TopProperty));
rect.RenderTransform = new TranslateTransform(0d, 0d);
rect.Opacity = 0.6;
this.canvas.Children.Add(rect);
this.btn.IsDrag = true;
}
}
///
/// 区域鼠标左键抬起
///
private void CanvasButtonLeftUp(object sender, MouseButtonEventArgs e)
{
if (this.btn.IsDrag)
{
this.btn.SetValue(Canvas.LeftProperty, this.btn.CurrentPos.X);
this.btn.SetValue(Canvas.TopProperty, this.btn.CurrentPos.Y);
Rectangle rect = LogicalTreeHelper.FindLogicalNode(this, "rect") as Rectangle;
this.canvas.Children.Remove(rect);
this.btn.IsDrag = false;
}
}
}
四. 原理图
五. 运行效果
六. 工程代码
下载地址
WPF实现鼠标拖动控件并带有中间动效
标签:type div drag int sele sch ora 封装 鼠标移动
原文地址:https://www.cnblogs.com/Jeffrey-Chou/p/12249596.html
评论