我什么时候应该使用装饰品?

fra*_*fra 47 wpf adorner

WPF非常棒,因为有很多方法可以实现您的目标.例如,根据我的理解,装饰者可以向UI元素添加一些控件,但我认为通过包含附加元素的自定义控件可以实现相同的行为.

所以,我的问题是:我应该何时更喜欢装饰者更复杂(但我认为,更灵活)的自定义控制?请考虑我正在广泛使用MVVM模式,我想将命令绑定到附加元素.

特别是,我正在设计一个图表设计器应用程序,我想为我的形状添加连接点.我应该在自定义控件和装饰器之间做出决定的另一个示例是显示自动定位以"跟随"该线的标签的线.

谢谢

Ray*_*rns 76

在大多数情况下,Adorners比使用ControlTemplates需要更多的工作.如果您想要装饰者提供的其他功能,请使用它们.否则使用ControlTemplates.

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

  1. 由于装饰品位于单独的图层上,因此视觉效果可以延伸到装饰元素之外,即使装饰元素被剪裁也是如此.
  2. 由于装饰器位于单独的图层上,因此它们通常不会被AdornedElement的容器或兄弟控件遮挡.
  3. 自动向装饰者通知装饰元素的大小和位置的所有变化,从而允许响应布局变化,这些变化不是普通控制所难以实现的.
  4. 可以将装饰器应用于面板和现有控件,而无需对其模板或其他方式进行任何更改.这使它们适合于在任意控件上提供操作句柄或视觉反馈.
  5. 在许多情况下,您只会为数百或数千个"活动"项目创建装饰器.如果必须向模板添加一个额外的Panel,那么使用ControlTemplates实现相同的功能可能会大大降低效率:模板的每个单独实例都将具有额外的面板,而只有一个装饰器.

以下是与使用装饰相关的一些潜在成本,而不是ControlTemplates:

  1. 您必须编写代码来调用.GetAdornerLayer().Add()管理Adorner的生命周期
  2. 您必须为您的Adorner编写渲染代码或添加代码以包含Control作为装饰器的子级,以便您可以使用ControlTemplate
  3. 您通常会在代码中进行自定义度量/排列计算(除非您在装饰器中使用ControlTemplate)
  4. RoutedEvents如果您希望目标控件处理它们,则需要转发到AdornedElement
  5. DataContext="{Binding AdornedElement.DataContext}"如果要将DataContext放在一起,则需要添加一个
  6. 看起来在每个布局通道上都会扫描可见的Adorner,因此一次在屏幕上显示数千个装饰器会导致明显的减速.(普通视觉效果只有当直接影响它们的东西发生变化时才会调用它们的度量/排列代码.)
  7. 不支持超过144个装饰者,因此如果有接近此限制的风险,控制模板更适合.

在您的特定示例中,没有明确的正确答案.

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

  • 如果线条不是简单的直线,那么自动定位的标签可能非常适合测量/排列计算的角度,但如果您可能同时看到其中的一万个,我会关注性能.

在不了解您的应用程序的情况下,很难说更多.

  • 非常感谢,这是一个伟大而完整的答案.该应用程序是一个UML设计器,所以我不认为我会有太多的连接; 无论如何,通常他们不是直线. (3认同)