WPF装饰者有什么意义?

So *_*ins 4 .net wpf adorner adornerdecorator adornerlayer

我最近为我的公司开发了一个绘图组件,其中包含一个Canvas,您可以使用点击并拖动来绘制某些形状.对于每个形状,我在其AdornerLayer上放置了两个装饰器:一个用于增加命中检测(基本上是一个透明的矩形,将超过形状的边界几个像素),另一个用于调整大小(角上的四个Thumb控件).

但是,在实现组件的某些功能时遇到了许多问题,所有与装配器相关.

  • 他们捕获了所有预览事件,因为它们在另一个视觉树中而不是Canvas本身,这是出乎意料的,但我发现了一种解决方法,即使我不喜欢它.使用AdornerDecorator并没有解决这个问题,我实施的选择装饰器是预览事件的黑洞.

  • 当我在Canvas上实现形状的z-index操作(发送回来,带到前面等)时,使用Panel.SetZIndex可以正常工作,正如您所期望的那样.但是,装饰者在另一个视觉树中!所以它们没有受到影响,选择装饰品仍然在所有其他形状之上,即使这些形状位于选择装饰器检测到的形状之上.例如:Shape1,SelectionAdorner1.Shape2,SelectionAdorner2.Shape1位于Shape2的顶部(稍后添加到画布),因此它与它重叠.因此,SelectionAdorner1将检测到它的点击.我操纵ZIndex将它发送回去,现在Shape2在顶部并与Shape1重叠.我单击Shape2顶部,但SelectionAdorner1而不是SelectionAdorner2检测到单击.这特别令人讨厌.所以,显然自从Adorners在另一个视觉树上,他们不尊重ZIndexes.我尝试通过在形状的ZIndex和其SelectionAdorner的ZIndex之间创建DataBinding(以及通过手动设置)来解决它.但这并没有解决问题.改变装饰器的Z-索引并没有影响他们在屏幕上显示的方式,也许我失去了一些东西,但它不应该是真的这个又硬,因为装饰器都应该是取得了令事情变得更容易.我能想出的唯一解决方案是手动删除所有装饰器并逐个手动添加它们,最后添加一个应该在顶部的装饰.这是迟钝的,但它奏效了.

  • 接下来,Adorners不尊重ClipToBounds!我在Canvas中设置了ClipToBounds = true,我正在绘制它,它工作得很好,但该死的装饰者仍然可以工作!对此的解决方案相对无痛,我只是在每个Shape上添加了一个AdornerDecorator.不是理想的解决方案IMO,但足够简单.

  • 装饰者并不总是对在其装饰元素上执行的LayoutTransforms做出很好的反应.我在画布顶部有一个Panel,它实现了Zoom和Pan功能.它使用动画来使放大和缩小更加平滑.但是使用动画会让我的Adorners变得猿!第一次缩放他们只是忽略调整大小并保持相同的大小和位置,在第二次缩放时,他们将缩放到装饰元素的先前大小.这没有任何意义!我能找到的唯一解决办法就是禁用动画,谢天谢地,这很有用

我不太记得我有哪些其他问题,但这足以让我想起Adorners的用处,我正在认真考虑不在我的下一个项目中使用它们,这类似于我描述的那个.

那么,任何人都可以告诉我使用这些看似有用但令人难以置信的令人烦恼的东西的可能性是什么?

谢谢.

Cha*_*lie 8

我想你已经知道了你的问题的答案.它们在某些方面节省了时间,并在其他方面引起问题.如果您使用各种UserControl来编写此设计器行为代码,您会发现自己编写了许多样板控件类来包装您实际想要编辑的元素.另一方面,如果您尝试编写单独的编辑控件并智能地覆盖它们,那么您将编写样板代码以保持其位置和大小同步.您使用装配器采用的方法导致了大量(相当样板)代码来管理事件.

虽然装饰者可能不是这项特定任务的最佳工具,但它们仍然是其他更简单任务的有用工具.我最近写了一个类似的"设计表面",装饰师是两件作品的天赐之物:

  1. 拖放行为.当我拖动不同的元素时,他们需要有不同的视觉预览; 使用自定义装饰器和数据模板非常容易实现.
  2. 选择矩形或"套索".当您在Windows桌面上按住鼠标左键并拖动指针时,可以看到类似的内容.它创建了一个可以选择多个元素的半透明框.我几乎可以立即使用adorner层创建此行为,而创建自己的自定义控件会导致大量不必要的簿记.

我认为你在项目中发现的是你可能一直在使用装饰来试图完成太多.但是不要把婴儿扔出洗澡水 - 在某些情况下它们仍然非常有用.