【发布时间】:2011-09-14 07:30:08
【问题描述】:
我最近为我的公司开发了一个绘图组件,其中包含一个 Canvas,您可以在其上使用单击并拖动来绘制某些形状。对于每个形状,我在其 AdornerLayer 上放置了两个装饰器:一个用于增加命中检测(基本上是一个透明矩形,将超出形状的边界几个像素),另一个用于调整大小(角落上有四个 Thumb 控件)。
但是,我在实现组件的一些功能时遇到了很多问题,所有这些都与装饰器相关。
他们捕获了所有预览事件,因为它们位于画布本身之外的另一个视觉树中,这是出乎意料的,但我找到了一种解决方法,即使我不太喜欢它。使用 AdornerDecorator 并没有解决这个问题,我实现的选择装饰器是预览事件的黑洞。
当我在 Canvas 上实现形状的 z-index 操作(发送到后面、带到前面等)时,它使用 Panel.SetZIndex 可以正常工作,正如您所期望的那样。但是,装饰器在另一个视觉树中!因此它们不会受到影响,并且选择装饰器仍然位于所有其他形状之上,即使这些形状位于选择装饰器正在检测命中的形状之上。 例如: 形状 1,选择装饰器 1。 形状 2,选择装饰器 2。 Shape1 位于 Shape2 的顶部(稍后添加到画布),因此它与它重叠。因此,SelectionAdorner1 将检测到单击它。我操纵 ZIndex 将其发送到后面,现在 Shape2 位于顶部并与 Shape1 重叠。我单击 Shape2 的顶部,但单击是由 SelectionAdorner1 而不是 SelectionAdorner2 检测到的。 这特别烦人。因此,显然由于 Adorners 在另一个可视化树上,它们不尊重 ZIndexes。我试图通过在形状的 ZIndex 和其 SelectionAdorner 的 ZIndex 之间创建一个 DataBinding(也可以通过手动设置)来解决它。但这并没有解决问题。更改 Adorners 的 ZIndex 并不会影响它们在屏幕上的显示方式,也许我错过了一些东西,但它不应该真的这么难,因为 Adorners 应该让事情变得更容易。我能想出的唯一解决方案是手动删除所有装饰器,然后一个接一个地手动添加它们,最后添加应该在顶部的那个。这有点迟钝,但它奏效了。
接下来,装饰器不尊重 ClipToBounds!我在画布上设置 ClipToBounds=true,效果很好,但该死的装饰器仍然可以工作!解决这个问题的方法相对简单,我只是在每个 Shape 的顶部添加了一个 AdornerDecorator。 IMO 不是一个理想的解决方案,但足够简单。
装饰器并不总是对在其装饰元素上执行的 LayoutTransform 反应良好。我在画布顶部有一个面板,它实现了缩放和平移功能。它使用动画使放大和缩小更加平滑。但是使用动画导致我的 Adorners 变成了猿猴!第一次缩放他们会简单地忽略调整大小并保持相同的大小和位置,在第二次缩放时他们会缩放到装饰元素的 previous 大小。那没有任何意义!我能找到的唯一解决方案是禁用动画,谢天谢地
我不太记得我还有哪些其他问题,但这足以让我怀疑 Adorner 的用处,我正在认真考虑在我的下一个项目中不使用它们,这类似于我描述的一个。
那么,谁能告诉我使用这些看似有用但令人难以置信的烦人的东西有什么好处?
谢谢。
【问题讨论】:
标签: .net wpf adorner adornerlayer adornerdecorator