【问题标题】:What's the point to WPF adorners?WPF 装饰器有什么意义?
【发布时间】: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


    【解决方案1】:

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

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

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

    我认为您在项目中发现的是,您可能一直在使用装饰器来尝试完成太多事情。但是不要把婴儿和洗澡水一起扔出去——它们在某些情况下仍然非常有用。

    【讨论】:

    • 您说的非常对,您的示例可能对我有用,特别是因为我需要类似的拖放操作,感谢您的提示。
    猜你喜欢
    • 2013-02-06
    • 2013-01-12
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2020-02-21
    • 2019-01-20
    • 2016-11-24
    • 1970-01-01
    相关资源
    最近更新 更多