装饰器是一种特殊的类型 FrameworkElement,用于向用户提供视觉提示。 除其他用途外,装饰器还可用于向元素添加功能句柄或提供有关控件的状态信息。
关于装饰元素
一个 Adorner 自定义 FrameworkElement 是绑定到一个 UIElement。 装饰器在一个 AdornerLayer渲染界面中呈现,该渲染界面始终位于被装饰元素或被装饰元素集合之上。 装饰器的呈现与其绑定的UIElement的呈现是独立的。 装饰器通常相对于其绑定元素进行定位,使用位于被装饰元素左上角的标准 2D 坐标原点。
常见的装饰物用途包括:
- 将功能手柄添加到 UIElement,使用户能够以某种方式操作元素(重设大小、旋转、重新定位等)。
- 提供视觉反馈以指示各种状态,或响应各种事件。
- 在UIElement上覆盖视觉装饰
- 以视觉方式屏蔽或覆盖UIElement的部分或全部。
Windows Presentation Foundation (WPF)提供了一个用于装饰视觉元素的基本框架。 下表列出了装饰对象时使用的主要类型及其用途。 下面提供了几个用法示例:
班级 | DESCRIPTION |
---|---|
Adorner | 所有具体装饰器实现都继承自的抽象基类。 |
AdornerLayer | 表示用于一个或多个被装饰元素的装饰器呈现层的类。 |
AdornerDecorator | 一个类,允许修饰层与元素集合相关联。 |
实现自定义装饰器
Windows Presentation Foundation (WPF) 提供的装饰器框架主要用于支持创建自定义装饰器。 通过实现从抽象 Adorner 类继承的类来创建自定义装饰器。
注释
Adorner的父级是渲染Adorner的AdornerLayer,而不是被装饰的元素。
以下示例演示一个实现简单装饰器的类。 示例装饰器只是给 UIElement 的角落加上圆圈。
// 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);
}
}
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
下图显示了应用于TextBox的 SimpleCircleAdorner:
装饰器呈现行为
请务必注意,修饰器没有固有的呈现行为;确保修饰器呈现是由修饰器的实现者负责。 实现渲染行为的一种常见方法是重写 OnRender 方法,并根据需要使用一个或多个 DrawingContext 对象来呈现装饰器的视觉效果(如上面的示例所示)。
注释
装饰器层中放置的任何内容都呈现在设置的任何样式的其余部分之上。 换句话说,装饰器总是在视觉层次上位于顶部,并且无法通过 z 轴顺序来覆盖。
事件和命中测试
装饰器接收输入事件就像任何其他 FrameworkElement 一样。 由于装饰器始终具有比它装饰的元素更高的 z 顺序,因此装饰器接收可能用于基础装饰元素的输入事件(如 Drop 或 MouseMove)。 装饰器可以侦听某些输入事件,并通过重新引发事件将这些事件传递给基础装饰元素。
要启用装饰层下元素的透传命中测试,请将装饰层的命中测试IsHitTestVisible属性设置为假。 有关命中测试的详细信息,请参阅 视觉层中的命中测试。
单一UI元素的装饰
若要将装饰器绑定到特定的UIElement,请按照以下步骤操作:
调用静态方法 GetAdornerLayer 来获取 AdornerLayer 对象,用于装饰 UIElement。 GetAdornerLayer 从指定的 UIElement开始,遍历可视化树,并返回找到的第一个装饰层。 (如果未找到装饰器层,则该方法返回 null。
以下示例将 SimpleCircleAdorner(如上所示)绑定到 TextBox 名为 myTextBox:
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SimpleCircleAdorner(myTextBox));
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox)
myAdornerLayer.Add(New SimpleCircleAdorner(myTextBox))
注释
目前不支持使用可扩展应用程序标记语言(XAML)将装饰器绑定到另一个元素。
装饰面板的子元素
若要将装饰器绑定到 Panel 的子元素,请按照以下步骤操作:
要调用
static
方法GetAdornerLayer,以查找用于装饰其子元素的元素的装饰层。依次枚举父元素的子级并调用 Add 方法,以将装饰器绑定到每个子元素。
以下示例将 SimpleCircleAdorner(如上所示)绑定到名为 myStackPanel 的StackPanel子级:
foreach (UIElement toAdorn in myStackPanel.Children)
myAdornerLayer.Add(new SimpleCircleAdorner(toAdorn));
For Each toAdorn As UIElement In myStackPanel.Children
myAdornerLayer.Add(New SimpleCircleAdorner(toAdorn))
Next