我最近为我的公司开发了一个绘图组件,其中包含一个画布,您可以在上面通过单击并拖动来绘制某些形状。对于每个形状,我在其 AdornerLayer 上放置了两个装饰器:一个用于增加命中检测(基本上是一个会超出形状边界几个像素的透明矩形),另一个用于调整大小(角上的四个拇指控件)。
但是,在实现组件的一些功能时,我遇到了很多问题,所有这些问题都与装饰器相关。
-
他们捕获了所有预览事件,因为它们位于画布本身之外的另一个视觉树中,这是出乎意料的,但我找到了一个解决方法,即使我不太喜欢它。使用 AdornerDecorator 并没有解决这个问题,我实现的选择装饰器是预览事件的黑洞。
-
当我在 Canvas 上实现形状的 z-index 操作(发送到后面、带到前面等)时,正如您所期望的那样,使用 Panel.SetZIndex 效果很好。但是,装饰器位于另一个视觉树中!因此它们没有受到影响,并且选择装饰器仍然位于所有其他形状之上,即使这些形状位于选择装饰器正在检测命中的形状之上。
例如:
形状 1,选择装饰器 1。
形状 2、选择装饰器 2。
Shape1 位于 Shape2 的顶部(稍后添加到画布),因此它与 Shape2 重叠。因此,SelectionAdorner1 会检测到对它的点击。我操纵 ZIndex 将其发送到后面,现在 Shape2 位于顶部并与 Shape1 重叠。我单击 Shape2 顶部,但该单击是由 SelectionAdorner1 而不是 SelectionAdorner2 检测到的。
这特别烦人。因此,显然由于装饰器位于另一个视觉树上,因此它们不尊重 ZIndexes。我尝试通过在形状的 ZIndex 和其 SelectionAdorner 的 ZIndex 之间创建 DataBinding(以及手动设置)来解决该问题。但这并没有解决问题。改变装饰器的 ZIndex 并不会影响它们在屏幕上的显示方式,也许我错过了一些东西,但它不应该真的这么难,因为装饰器应该让事情变得更容易。我能想到的唯一解决方案是手动删除所有装饰器,然后再一一手动添加它们,最后添加应该位于顶部的装饰器。虽然这有点迟缓,但它确实有效。
-
接下来,装饰者不尊重 ClipToBounds!我在我正在绘制的画布中设置了 ClipToBounds=true ,效果很好,但该死的装饰器仍然可以工作!这个问题的解决方案相对轻松,我只是在每个形状的顶部添加了一个 AdornerDecorator。在我看来,这不是一个理想的解决方案,但足够简单。
-
装饰者并不总是对在其装饰元素上执行的 LayoutTransforms 做出良好的反应。我在画布顶部有一个面板,它实现缩放和平移功能。它使用动画来使放大和缩小更加平滑。但是使用动画导致我的装饰者变得疯狂!第一次缩放时,他们会简单地忽略调整大小并保持相同的大小和位置,在第二次缩放时,他们会缩放到previous装饰元素的大小。那没有任何意义!我能找到的唯一解决方案是禁用动画,谢天谢地,这有效
我不太记得我遇到了哪些其他问题,但这足以让我想知道装饰器的有用性,并且我正在认真考虑不在我的下一个项目中使用它们,该项目与我描述的项目类似。
那么,谁能告诉我使用这些看似有用但非常烦人的东西可能有什么优点呢?
我想你已经知道你的问题的答案了。它们在某些方面节省了时间,但在其他方面却造成了问题。如果您要使用各种 UserControl 来编写此设计器行为,您会发现自己编写了大量样板控件类来包装您实际想要编辑的元素。另一方面,如果您尝试编写单独的编辑控件并智能地覆盖它们,您将编写样板代码以保持它们的位置和大小同步。您采用的方法(使用装饰器)产生了大量(相当样板的)代码来管理事件。
虽然装饰器可能不是最好的工具特别的任务,它们仍然是执行其他更简单任务的有用工具。我最近写了一个类似的“设计表面”,装饰器是两件作品的天赐之物:
- 拖放行为。当我拖动不同的元素时,它们需要有不同的视觉预览;使用自定义装饰器和数据模板可以非常轻松地完成此任务。
- 选择矩形或“套索”。当您在 Windows 桌面上按住鼠标左键并四处拖动指针时,您可以看到类似的内容。它创建一个可以选择多个元素的半透明框。我几乎可以使用装饰层立即创建此行为,而创建我自己的自定义控件会导致大量不必要的簿记。
我认为您在项目中发现的是,您可能一直在使用装饰器来尝试完成太多任务。但不要把婴儿和洗澡水一起倒掉——它们在某些情况下仍然非常有用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)