Общие сведения о декоративных элементах

Декоративные элементы являются специальным типом элементов FrameworkElement, который используется для предоставления визуальных подсказок пользователю. Помимо прочего, декоративные элементы можно использовать для добавления функциональных дескрипторов к элементам или предоставления информации о состоянии элемента управления.

Сведения о декоративных элементах

Adorner — это пользовательский FrameworkElement, привязанный к UIElement. Декоративные элементы отображаются в AdornerLayer, который является поверхностью отрисовки, всегда располагающейся поверх декорированного элемента или коллекции декорированных элементов. Отрисовка декоративного элемента не зависит от отрисовки UIElement, к которому привязан декоративный элемент. Декоративный элемент обычно располагается относительно элемента, к которому он привязан, с использованием стандартной двухмерной системы координат с началом отсчета в левом верхнем углу декорируемого элемента.

Типичные сценарии использования декоративных элементов:

  • Добавление функциональных обработчиков к UIElement, которые позволяют пользователю свободно манипулировать элементом (изменять размеры, вращать, перемещать и т. д.).
  • Обеспечение визуальной обратной связи для указания различных состояний или в ответ на различные события.
  • Наложение визуальных декоративных элементов на UIElement.
  • Визуальная маскировка или переопределение части или всех UIElement.

Windows Presentation Foundation (WPF) предоставляет базовую платформу для оформления визуальных элементов. В следующей таблице перечислены основные типы, используемые при настройке объектов, и их назначение. Ниже приведено несколько примеров использования:

Класс Description
Adorner Абстрактный базовый класс, из которого наследуются все конкретные реализации декоративного элемента.
AdornerLayer Класс, представляющий слой отрисовки декоративного элемента одного или нескольких настроенных элементов.
AdornerDecorator Класс, который позволяет ассоциировать слой декоративного элемента с коллекцией элементов.

Реализация пользовательского декоративного элемента

Среда декоративных элементов, предоставляемая Windows Presentation Foundation (WPF), предназначена в первую очередь для поддержки создания пользовательских декоративных элементов. Пользовательский декоративный элемент создается путем реализации класса, который наследуется от абстрактного класса Adorner.

Примечание.

Родительским элементом Adorner является AdornerLayer, отрисовывающий Adorner, а не декорируемый элемент.

В следующем примере показан класс, который реализует простой декоративный элемент. В этом примере декоративный элемент просто скругляет углы элемента 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

На следующем рисунке показан элемент SimpleCircleAdorner, примененный к TextBox.

Screenshot that shows an adorned text box.

Поведение отрисовки для декоративных элементов

Важно отметить, что декоративные элементы не включают какое-либо обязательное поведение отрисовки. За результат применения декоративного элемента отвечает его автор. Обычно для реализации поведения отрисовки переопределяется метод OnRender и с помощью одного или нескольких объектов DrawingContext отображаются визуальные компоненты декоративного элемента (см. пример выше).

Примечание.

Все, что помещено в слой декоративного элемента, отрисовывается поверх остальных установленных стилей. Другими словами, декоративные элементы всегда визуально находятся сверху и не могут быть переопределены с помощью упорядочения по z-координате.

События и проверка нажатия

Декоративные элементы получают входящие события, как и любые другие FrameworkElement. Поскольку у декоративного элемента всегда более высокий z-порядок, чем у элемента, который он декорирует, он получает входящие события (такие как Drop или MouseMove), которые могут быть предназначены для базового декорируемого элемента. Декоративный элемент может отслеживать определенные события ввода и передавать их в базовый декорированный элемент, повторно запуская событие.

Чтобы включить сквозную проверку нажатия для элементов под декоративным элементом, задайте для свойства IsHitTestVisible проверки нажатия значение false в декоративном элементе. Дополнительные сведения о проверке нажатия см. в разделе Проверка нажатия на визуальном уровне.

Декорирование одного элемента пользовательского интерфейса

Чтобы привязать декоративный элемент к определенному элементу UIElement, выполните следующие действия:

  1. Вызовите статический метод GetAdornerLayer, чтобы получить объект AdornerLayer для элемента UIElement, который нужно оформить. Метод GetAdornerLayer проходит по визуальному дереву, начиная с заданного элемента UIElement, и возвращает первый найденный слой декоративных элементов. (Если слои декоративных элементов не найдены, метод возвращает значение 0.)

  2. Вызовите метод Add, чтобы привязать декоративный элемент к целевому элементу UIElement.

В следующем примере элемент SimpleCircleAdorner (см. выше) привязывается к элементу TextBox с именем myTextBox:

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

Примечание.

Привязка графического элемента к другому элементу в коде XAML на данный момент не поддерживается.

Декорирование дочерних объектов панели

Чтобы привязать декоративный элемент к дочерним элементам Panel, выполните следующие действия:

  1. Вызовите метод staticGetAdornerLayer, чтобы найти слой декоративного элемента для объекта, дочерние элементы которого нужно оформить.

  2. Перечислите дочерние элементы родительского элемента и вызовите метод Add, чтобы привязать графический элемент к каждому из них.

В следующем примере элемент SimpleCircleAdorner (см. выше) привязывается к дочерним элементам панели StackPanel с именем myStackPanel:

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

См. также