当前位置:首页 > Windows程序 > 正文

解决拖动行为附加到元素上的延迟

2021-05-25 Windows程序

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

——————————————————

今天着重把 MouseDragElementBehavior 类看明白了,并把源代码调整了下,基本可用了。

最终的使用方式看起来是这样的

<DataTemplate DataType="vm:MyItemViewModel">   <Border Width="120" Height="30" Background="Red">     <i:Interaction.Behaviors>       <ib:MouseDragElementBehavior X="{Binding Left, Mode=TwoWay}" Y="{Binding Top, Mode=TwoWay}" />     </i:Interaction.Behaviors>     <TextBlock HorizontalAlignment="Center" Foreground="White" VerticalAlignment="Center" Text="{Binding Show}" />   </Border> </DataTemplate>

然而这个时候,我是在 DataTemplete 中的Border根节点附加的 拖动行为。

总感觉哪里不对,,哪里不对呢,拖动的时候有细微的晃动,并且Border不应该被用来干拖动这样的事情,另外没有有效的利用路由事件的优势。

这时我对使用 ItemsControl 这个控件产生了怀疑,跑去研究了下ListView,看了下官方ListView四种示例的Demo(地址)认真看完Demo的具体使用方式,发觉这和我想要的东西相差甚远,ListView主要的用途是可以以自定义视图展示可视项,想来想去还是回到ItemsControl 的怀抱上来吧,暂时先以 ItemsControl + Canvas 的组合前提下做调整吧。

仔细分析 MouseDragElementBehavior ,最后发现官方这个类的实现竟然和窗口复杂度有关!

里面有这样一个觉得不好的属性的实现:

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/70718.html