此文的前提是%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 对元素进行捕获就可以了