何时应该使用装饰器?

56

WPF很棒,因为有许多方法可以实现你的目标。例如,据我所知,装饰器可以向UI元素添加一些控件,但我认为通过包含附加元素的自定义控件也可以实现相同的行为。

那么,我的问题是:在什么情况下应该优先使用装饰器,而不是更复杂(但我认为更灵活)的自定义控件? 请考虑到我广泛使用MVVM模式,并且我想将命令绑定到附加元素。

特别是,在设计图表设计器应用程序时,我想向我的形状添加连接点。另一个需要在自定义控件和装饰器之间进行选择的示例是显示一个标签的线,该标签自动定位以“跟随”该线。

谢谢

1个回答

90

相较于使用 ControlTemplates,在大多数情况下,Adorners 需要做更多的工作。如果你想使用 Adorners 提供的额外功能,请使用它们。否则请使用 ControlTemplates。

以下是 Adorners 带来的主要功能:

  1. 由于 Adorners 在单独的层上,即使被装饰元素被裁剪,视觉效果也可以延伸到其之外。
  2. 由于 Adorners 在单独的层上,它们通常不会被 AdornedElement 的容器或兄弟控件遮挡。
  3. Adorners 自动收到所有关于被装饰元素大小和位置的变化的通知,因此可以对布局变化作出响应,这是普通控件达成的效果不太容易的。
  4. Adorners 可以应用于面板和现有控件,无需对其模板进行任何更改。这使得它们非常适合为任意控件提供操作句柄或可视反馈。
  5. 在许多情况下,你只需要为数百个或数千个条目中的几个“活动”项目创建 adorners。如果你必须向模板添加一个额外的 Panel,则使用 ControlTemplates 实现相同的功能可能效率显著降低:每个模板的实例都会有额外的面板,而只有一个 adorner。

以下是使用 Adorners 相对于 ControlTemplates 可能存在的一些成本:

  1. 你必须编写调用 .GetAdornerLayer().Add() 的代码,并管理 Adorner 的生命周期。
  2. 你必须为你的 Adorner 编写渲染代码,或者添加代码将 Control 作为 Adorner 的子元素,以便可以使用 ControlTemplate。
  3. 通常你需要在代码中执行自定义的尺寸计算和布局排列(除非你在 Adorner 中使用 ControlTemplate)。
  4. 如果你想要处理目标控件的路由事件,则需要将这些事件转发到 AdornedElement。
  5. 如果你想要将 DataContext 带入,请添加 DataContext="{Binding AdornedElement.DataContext}"
  • 看起来可见的 Adorner 在每个布局传递中都会被扫描,所以在屏幕上同时拥有成千上万的 adorner 可能会导致明显的减速。(普通的可视元素只有当直接影响它们的东西发生变化时,它们的测量/排列代码才会被调用。)
  • 不支持使用超过 144 个 adorner,因此如果存在任何接近此限制的风险,则控件模板更加合适。
  • 在您的特定示例中,没有明确的正确答案。

    • 我倾向于为连接点使用 ControlTemplate,因为您可能需要一种指定连接点位置的方法,而 ControlTemplate 已经定义了项本身的布局。另一方面,如果连接点信息是数据驱动的,并且仅出现在活动控件(或正在拖动的控件)上,那么使用 adorner 来获得性能优势并简化单个 ControlTemplate 可能更好。

    • 如果线条不是简单的直线,则自动定位的标签从测量/排列计算的角度来看可能非常适合作为 adorner,但如果您可能会同时看到成千上万个这些标签,我会担心性能问题。

    如果不了解您的应用程序,很难说更多的内容。


    3
    非常感谢,这是一个很好而且完整的回答。 该应用程序是一个UML设计工具,因此我认为我不会有太多的连接;无论如何,通常它们都不是直线。 - fra

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接