WPF开发日记—解决拖动行为附加到元素上的延迟

本文讲述了作者在WPF中使用ItemsControl动态添加控件并实现拖动功能时遇到的延迟问题。通过分析,作者发现Canvas.SetLeft存在延迟,而微软的MouseDragElementBehavior行为在复杂窗口中表现不佳。作者决定重写拖动行为,采用RenderTransform优化,减少延迟。最后,作者发现允许透明(AllowsTransparency)设置为True会导致性能问题,并决定禁用该设置以提高拖动流畅性。
摘要由CSDN通过智能技术生成

此文的前提是%26nbsp;结合ItemsControl在Canvas中动态添加控件的最MVVM的方式

%26nbsp;

上一篇博客讲到了我通过使用 ItemsControls 内部设置Canvs为布局面板

并在ItemContainerStyle中设置Canvs.Left, Canvas.Top。

来实现设置MVVM模式下自定义位置显示单项内容的功能。

接下来的一步要显示内容的拖动。

很抱歉的告诉大家,经过这两天的探索,我打算推翻上面的做法。

虽然可以这样用,学到了些东西,但是效果并不是很好。

%26nbsp;

原因在于,当后面我需要给 Item 加上一个可拖动的功能时,就出现问题了。

我起初是这样做的:创建了一个自定义的可拖动行为类(DragMoveBehavior),

我本是先要测试下通过行为设置 Canvas.Left, Canvas.Top 是否是可用的,

实现了以后,我新建了个测试窗体,放进去一个Canvas,里面再随便塞了一个矩形(Rectangle),给矩形添加了我自定义的拖动行为。

问题很快就出现了,当我拖动的太快,矩形根不上我的鼠标速度,就被丢下了,不再跟着我走。

理想状态下,应该是我拖动的再快,矩形再小,也应该无时差的一直跟着我的鼠标走才对啊。

虽然稍微慢点是可以跟着走的,但我无论如何不能忍受这样的操作体验。

我测试来测试去,发现Canvas.SetLeft是有细微的延迟的。

未经严格证实的猜测是鼠标移动和设置位置两个任务,在主线程的处理优先级是不一致的(DispatcherPriority)。

这个时候,鼠标每移动一个像素点,都需要不断的Canvas.SetLeft,重复不停的布局操作无疑不是很好的选择。

%26nbsp;

想到 Blend 里面的行为自带了%26nbsp;MouseDragElementBehavior 行为拖动效果,测试发现这个功能在操作上是没有瑕疵的。

然而我并不能直接拿来用。因为相关的位置数据是要读取和保存的,而不只是有一个拖动效果。

所以我直接用 dotPeek 反编译看下微软是怎么实现的。%26nbsp;dotPeek 果然强大,最大的特点是 每个方法都生成了非常完整的中文注释。甚至直接查看基类,也有完整的代码和中文注释。

而我同时用%26nbsp;Reflector %26nbsp;反编译没有注释还报错。 ILSpy 只有部分方法有中文注释。
哦,原来微软用的是%26nbsp;RenderTransform 呈现变形!好东西,我怎么又没想到呢?

不过微软写的比较复杂,600多行代码,用了矩阵变形,实现了变形深克隆,内置了X,Y的依赖属性等等。

依赖属性?难道可以直接用?试了下,不行,没有变化。

太困了,凌晨四点了,睡觉先。

趴在床上,准备睡觉,习惯性翻开mac爽爽vim,突然想到,苹果系统拖动效果是怎样的呢,测试了下,发现竟然有完全一样的问题,然而在鼠标瞬间脱离UI元素的时候,并没有失去鼠标捕获。捕获?哦,我懂了,如果用%26nbsp;MouseCapture 对元素进行捕获就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值