WPF DragDrop事件元素跟随
前一段时间项目里面要实现一个鼠标拖动一个元素到另外一个元素上面并且赋值的功能,由于要在surface上运行,拖动的时候手指会挡住系统默认的拖动图标,导致用户意识不到自己是不是在拖动着东西,所以要解决这个问题。
初始想法
一开始在的设想是,拖动开始时新建一个元素要拖动的元素,然后设置次元素跟随鼠标移动,这里遇到个问题就是,当使用DoDragDrop事件的时候,捕捉不到鼠标的坐标变动,以至于无法让新建的元素跟随移动。要实现功能必须放弃DoDragDrop事件,但是当时很多已经写好的功能都是围绕这个事件的,不想再改,于是开始探索新的方式,虽然一开始浪费了一点时间,但是好处也不是没有,比如发现了GiveFeedback事件,于是就想到了第二种方案。
由于本来就是没有实现的方法,所以在此就不上代码了。
第二种方案
ButtonDown触发的时候,给元素添加MouseMove事件,当MouseMove触发的时候,获取到当前元素并生成图像转换为Cursor格式,在GiveFeedback中用以改变鼠标样式,添加GiveFeedback事件并启动DoDrapDrop。
public void ViewElemenMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var viewElement = sender as ViewElement;
if (viewElemen == null) return;
viewElemen.MouseMove += ViewElemenOnPreviewMouseMove;
} private void PatientTitleOnPreviewMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var viewElement = sender as ViewElement;
if (viewElement == null) return;
HoloCursor = FormUtility.CreateCursor(viewElement);
viewElemen.RockStart();
viewElemen.GiveFeedback += DragSource_GiveFeedback;
DragDrop.DoDragDrop(viewElemen, Model, DragDropEffects.Copy);
viewElemen.MouseMove -= ViewElemenOnPreviewMouseMove;
viewElemen.GiveFeedback -= DragSource_GiveFeedback;
Mouse.SetCursor(Cursors.Arrow);
} void DragSource_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
var viewElement = sender as ViewElement;
if (viewElemen == null) return;
Mouse.SetCursor(HoloCursor);
e.UseDefaultCursors = false;
e.Handled = true;
}
之所以把这么麻烦是因为,鼠标点击事件还要有其他的业务操作,所以只能加在mousemove里面。
根据元素生成鼠标 FormUtility.CreateCursor:
public static Cursor CreateCursor(UIElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(new Point(), element.DesiredSize)); var rtb =
new RenderTargetBitmap(
(int)element.DesiredSize.Width,
(int)element.DesiredSize.Height,
96, 96, PixelFormats.Pbgra32); rtb.Render(element); var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb)); using (var ms = new MemoryStream())
{
encoder.Save(ms);
using (var bmp = new System.Drawing.Bitmap(ms))
{
return InternalCreateCursor(bmp);
}
}
}
private static Cursor InternalCreateCursor(System.Drawing.Bitmap bmp)
{
var iconInfo = new NativeMethods.IconInfo();
NativeMethods.GetIconInfo(bmp.GetHicon(), ref iconInfo); iconInfo.xHotspot = 125;
iconInfo.yHotspot = 65;
iconInfo.fIcon = false; SafeIconHandle cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
return CursorInteropHelper.Create(cursorHandle);
}
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
private class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeIconHandle()
: base(true)
{
} override protected bool ReleaseHandle()
{
return NativeMethods.DestroyIcon(handle);
}
}
private static class NativeMethods
{
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
} [DllImport("user32.dll")]
public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon); [DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr hIcon); [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
}
RockStart是一个元素效果,即开始拖动的时候,该元素会左右摇晃,让用户更清楚的知道,自己拖动的是哪个元素。
private Storyboard _sb = new Storyboard(){ FillBehavior = FillBehavior.Stop }; public ViewElement()
{
InitializeComponent();
_sb.AutoReverse = true;
var dbAscending1 = new DoubleAnimation(0, 3, new Duration(TimeSpan.FromMilliseconds(100)));
_sb.Children.Add(dbAscending1);
Storyboard.SetTarget(dbAscending1, Border);
Storyboard.SetTargetProperty(dbAscending1, new PropertyPath("(Rectangle.RenderTransform).(RotateTransform.Angle)"));
var dbAscending2 = new DoubleAnimation(3, -3, new Duration(TimeSpan.FromMilliseconds(200)));
_sb.Children.Add(dbAscending2);
Storyboard.SetTarget(dbAscending2, Border);
Storyboard.SetTargetProperty(dbAscending2, new PropertyPath("(Rectangle.RenderTransform).(RotateTransform.Angle)"));
} public void RockStart()
{
Dispatcher.InvokeAsync(() => _sb.Begin(), DispatcherPriority.Background);
}
至此,功能完成。
WPF DragDrop事件元素跟随的更多相关文章
- WPF 在事件中绑定命令(不可以在模版中绑定命令)
其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实现将命令绑定到事件中. 上一篇中我们介绍了MVVMLight中的命令的用法,那么仅仅知道命令是 ...
- WPF自学入门(三)WPF路由事件之内置路由事件
有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...
- WPF路由事件二:路由事件的三种策略
一.什么是路由事件 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件 ...
- WPF 在事件中绑定命令
导航:MVVMLight系列文章目录:<关于 MVVMLight 设计模式系列> 其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实 ...
- js进阶 12-3 如何实现元素跟随鼠标移动
js进阶 12-3 如何实现元素跟随鼠标移动 一.总结 一句话总结:获取鼠标位置,将鼠标位置设置为元素偏移即可. 1.用什么事件获取鼠标位置? 用mousemove可以获取鼠标移动的时候的位置 $(d ...
- WPF 路由事件 Event Routing
原文:WPF 路由事件 Event Routing 1.路由事件介绍 之前介绍了WPF的新的依赖属性系统,本篇将介绍更高级的路由事件,替换了之前的.net普通事件.相比.net的事件,路由事件具有更强 ...
- Win7/Win8/Win8.1/Win10下的DragEnter DragDrop事件不触发
Win7/Win8/Win8.1/Win10下的DragDrop事件不触发 2011-02-02 来自:博客园 字体大小:[大 中 小] 摘要:你的应用程序需要从windows资源管理器拖动文件到 ...
- Win7下的DragEnter、DragDrop事件不触发的解决方案
Win7与原来的XP和Win2003相比,安全控制方面更严格.比如,当我们以administrator登陆XP或Win2003时,运行所有的程序即是以管理员的身份启动的.但当以administrato ...
- javascript元素跟随鼠标在指定区域运动
元素跟随鼠标在指定区域运动通常是用在商城图片的放大镜中,下面是完整的Demo: <!DOCTYPE html> <html lang="en"> <h ...
随机推荐
- java解析xml的4种经典方法
========================================== xml文件 <?xml version="1.0" encoding="GB2 ...
- 队列理论和队列网络模型 queueing theory and queueing network model
1队列理论 1.1队列在生活中随处可见,例如排队买票,排队打饭,排队做地铁等等.那将诸如此类的队列抽象一下,可归纳为一下5要术: 到达过程arrival process 服务时间的分布 service ...
- maven + appium + testng + java之pom.xml
参考来源:<https://search.maven.org/remotecontent?filepath=io/appium/java-client/3.3.0/java-client-3.3 ...
- Oracle 事务
begin begin savepoint p1; DELETE FROM sys_re_xxx; //红色部分替换为需要一起执行的SQL即可 DELETE FROM SYS_xxxx; ...... ...
- js实现自动登陆的按钮
自动按钮,只要实现当移入是提示用户不要在公共地方使用自动登陆 主要用onmouseover函数,本来提示div隐藏,当移入时div显示. <style type="text/css&q ...
- javascript各种兼容性问题,不断更新
ie6-ie8 不支持textContent支持innerTextchrome 支持textContent innerTextfireFox 仅支持textContent不支持innerTe ...
- Java基础类库
1 main方法 运行java程序的参数: 下面详细讲解main 方法为什么采用这个方法签名 1.public 修饰符:Java类由jvm调用,为了让jvm可以自由调用这个main()方 ...
- FreeBSD下查看各软件版本命令
查看FreeBSD版本: uname -a root# uname -a FreeBSD power 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02 ...
- ERS-2卫星
ERS-2卫星是欧洲空间局的第二颗资源遥感卫星,携带有雷达测高仪.综合孔径雷达等多种科学仪器,是一颗多任务.多学科的科学考察卫星.[1] ERS-1 ERS-2 欧空局分别于1991年和1995年发射 ...
- HBase -ROOT-和.META.表结构
在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...