装饰器概述

更新:2007 年 11 月

装饰器是一种特殊类型的 FrameworkElement,用于向用户提供可视化提示。对于其他用户,装饰器可用于将功能控点添加到元素中或提供有关控件的状态信息。

本主题包括下列各节。

  • 关于装饰器
  • 实现自定义装饰器
  • 装饰器的呈现行为
  • 事件和命中测试
  • 装饰单个 UIElement
  • 装饰面板的子级
  • 相关主题

关于装饰器

Adorner 是绑定到 UIElement 的自定义 FrameworkElement。装饰器在 AdornerLayer 中呈现,这是一个始终位于装饰元素或装饰元素集合上方的呈现图面。装饰器的呈现独立于该装饰器所绑定到的 UIElement 的呈现。装饰器通常使用位于装饰元素左上部的标准 2-D 坐标原点,相对于其绑定到的元素进行定位。

装饰器的常见应用包括:

  • UIElement 添加功能控点,使用这些控点,用户可以通过某种方式(调整大小、旋转、重新定位等等)操作元素。

  • 提供可视反馈以指示各种状态,或响应各种事件。

  • UIElement 上叠加视觉效果。

  • 从视觉上遮盖或重写 UIElement 的一部分或全部。

Windows Presentation Foundation (WPF) 为装饰视觉元素提供一个基本框架。下表列出了装饰对象时使用的主要类型及其用途。下面是几个用法示例。

Adorner

一个抽象基类,所有具体装饰器的实现都从该类继承。

AdornerLayer

一个类,表示一个或多个装饰元素的装饰器的呈现层。

AdornerDecorator

一个类,使装饰器层与元素集合相关联。

实现自定义装饰器

Windows Presentation Foundation (WPF) 提供的装饰器框架主要用于支持创建自定义装饰器。您可以通过实现一个从抽象 Adorner 类继承的类来创建自定义装饰器。

说明:

Adorner 的父级为 AdornerLayer,它呈现的是 Adorner,而不是正在装饰的元素。

下面的示例演示一个实现简单装饰器的类。该示例装饰器使用圆简单地装饰 UIElement 的各角。

Public Class SimpleCircleAdorner
    Inherits Adorner
    Sub New(ByVal adornedElement As UIElement)
        MyBase.New(adornedElement)
    End Sub

    Protected Overrides Sub OnRender(ByVal drawingContext As System.Windows.Media.DrawingContext)
        MyBase.OnRender(drawingContext)
        Dim adornedElementRect As New Rect(AdornedElement.DesiredSize)
        Dim renderBrush As New SolidColorBrush(Colors.Green)
        renderBrush.Opacity = 0.2
        Dim renderPen As New Pen(New SolidColorBrush(Colors.Navy), 1.5)
        Dim renderRadius As Double
        renderRadius = 5.0

        'Draw a circle at each corner.
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius)
    End Sub
End Class
// Adorners must subclass the abstract base class Adorner.
public class SimpleCircleAdorner : Adorner
{
  // Be sure to call the base class constructor.
  public SimpleCircleAdorner(UIElement adornedElement)
    : base(adornedElement) 
  { 
  }

  // A common way to implement an adorner's rendering behavior is to override the OnRender
  // method, which is called by the layout system as part of a rendering pass.
  protected override void OnRender(DrawingContext drawingContext)
  {
    Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);

    // Some arbitrary drawing implements.
    SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green);
    renderBrush.Opacity = 0.2;
    Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
    double renderRadius = 5.0;

    // Draw a circle at each corner.
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius);
  }
}

下面的图像演示了应用于 TextBox 的 SimpleCircleAdorner。

装饰器示例:经过装饰的文本框

装饰器的呈现行为

注意:装饰器不包括任何继承呈现行为,确保装饰器呈现是装饰器实施者的责任。 实现呈现行为的常见方式是重写 OnRenderSizeChanged 方法,并使用一个或多个 DrawingContext 对象来按需呈现装饰器的视觉效果(如上述示例所示)。

说明:

放置在装饰器层中的所有内容均呈现在您已设置的任何其余样式的顶部。也就是说,装饰器始终以可见的方式位于顶部,无法使用 z 顺序重写。

事件和命中测试

装饰器就像任何其他 FrameworkElement 一样接收输入事件。 因为装饰器的 z 顺序总是高于它所装饰的元素,所以该装饰器接收可能适用于基础装饰元素的输入事件(例如 DropMouseMove)。 装饰器可以侦听某些输入事件,并通过重新引发这些事件将其传递给基础装饰元素。

若要对装饰器下的元素启用传递命中测试,请在装饰器上将命中测试 IsHitTestVisible 的属性设置为 false。 有关命中测试的更多信息,请参见

可视化层中的命中测试

装饰单个 UIElement

若要将装饰器绑定到特定的 UIElement,请按照以下步骤操作:

  1. 调用静态方法 GetAdornerLayer,为要装饰的 UIElement 获取一个 AdornerLayer 对象。GetAdornerLayer 从指定的 UIElement 开始沿着可视树向上走,返回它所发现的第一个装饰器层。(如果未发现装饰器层,则该方法返回 Null。)

  2. 调用 Add 方法将装饰器绑定到目标 UIElement

以下示例将 SimpleCircleAdorner(如上述所示)绑定到名为 myTextBoxTextBox

myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox)
myAdornerLayer.Add(New SimpleCircleAdorner(myTextBox))
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SimpleCircleAdorner(myTextBox));
说明:

目前不支持使用可扩展应用程序标记语言 (XAML) 将装饰器绑定到另一个元素。

装饰面板的子级

若要将装饰器绑定到 Panel 的子级,请按照下列步骤操作:

 

  1. 调用 static 方法 GetAdornerLayer 为要绑定其子级的元素查找一个装饰器层。

  2. 依次枚举父元素的子级并调用 Add 方法将装饰器绑定到每个子级元素。

以下示例将 SimpleCircleAdorner(如上所示)绑定到名为 myStackPanelStackPanel 的子级。

For Each toAdorn As UIElement In myStackPanel.Children
    myAdornerLayer.Add(New SimpleCircleAdorner(toAdorn))
Next

foreach (UIElement toAdorn in myStackPanel.Children)
  myAdornerLayer.Add(new SimpleCircleAdorner(toAdorn));

请参见

概念

WPF 中的形状和基本绘图概述

使用图像、绘图和 Visual 进行绘制

Drawing 对象概述

参考

AdornerHitTestResult

其他资源

装饰器帮助主题

装饰器示例