Adorner Architecture

The visual design experience requires adorners, which are special glyphs on the design surface. Adorners are usually attached to a target control, and they give the user a graphical means of adjusting the control's properties. For example, when you are designing a control, and you click a corner to resize it, the sizing glyph you click is an adorner.

The ability to draft, refine, and restyle adorners quickly and easily is important for the WPF Designer architecture. This overview explains how the WPF Designer adorner extensibility model makes it simple for you to create your own adorners for customizing the design experience for your controls.

The WPF Designer offers a flexible mechanism for displaying adorners. This mechanism is coupled with a flexible command system which allows adorners to respond to user input. You add adorners to a control by implementing the IProvideAttributeTable interface.

Types of Adorners

Adorners can model almost any visual design-time presentation, but some types of adorners appear repeatedly. The following table describes the commonly used adorners.

Adorner

Description

Grab handle

Enables moving and sizing a control; non-scaling.

Rail

Adds a marker or rule along one side of a control; non-scaling along a single axis.

Frame

Represents a control's bounds; scales along both axes.

Overlay

Captures mouse interactions in the region of the control; scales along both axes. Roughly equivalent to the Body Glyph in the System.ComponentModel designer framework.

Adorner Characteristics

The WPF Designer framework enables adorners which have the following characteristics.

  • Allow adorners to be derived from any UIElement class and to support Windows Presentation Foundation styles.

  • Allow for all size, position, and scaling to be specified independently for the horizontal and vertical dimensions.

  • Eliminate the need for an adorner base class. Adorner types may be derived from any UIElement type which meets your needs.

Creating Custom Adorners

Adorners are provided by the AdornerProvider feature provider. You can add an AdornerProvider feature to a class, which automatically adds adorners to the design surface. The following walkthroughs show you how to create custom adorners.

Adorner Extensibility

Adorners are added according to an adorner provider's policy. You add a policy to an AdornerProvider by adding the UsesItemPolicyAttribute to the class definition.

When the IsInPolicy check is satisfied, the adorner appears on the design surface.

You can add adorner providers to a control that offers adorners for a given policy. When the items in the policy change, the adorner feature connector queries for new adorner providers on new controls and displays an updated set of adorners.

The WPF Designer implements the PrimarySelectionAdornerProvider, which offers a set of adorners that are shown for the primary selection. Most custom adorner providers derive from this class.

Adorners and Layout

The most important issue for adorners is layout. Adorners require a wide variety of layout options. The specific stretching or scaling behavior for an adorner must be considered when the zoom setting is changed for the designer surface. Adorners must be able to size and position themselves according to the following schemes.

  • Relative to the applied style.

  • Relative to the adorned control’s size and position.

  • Relative to absolute pixel offsets.

  • Relative to the current zoom setting.

In WPF, the typical mechanism for controlling layout is the panel. The WPF Designer framework controls layout by using the AdornerPanel class to parent adorners for a given control on a design surface.

The AdornerPanel class offers methods which allow adorners to be sized and positioned relative to the adorned control. To specify the adorner location, use the SetAdornerHorizontalAlignment, SetAdornerVerticalAlignment, and SetAdornerMargin methods.

Note

When you add a control as an adorner to another control, the adorner control is arranged to match the width, height, and transform of the control it is adorning. This may result in clipping issues. The easiest solution to these clipping issues is to add your control to a Canvas, and then add the canvas as the adorner. The width and height of the Canvas is adjusted, but the Canvas control does not clip or size to its content, so that your control is arranged within the canvas only.

The following code example shows how to position an adorner above the target control.

' Setup the adorner panel.
' All adorners are placed in an AdornerPanel
' for sizing and layout support.
Dim myPanel = Me.Panel

' The slider extends the full width of the control it adorns.
AdornerPanel.SetAdornerHorizontalAlignment( _
    opacitySlider, _
    AdornerHorizontalAlignment.Stretch)

' Position the adorner above the control it adorns.
AdornerPanel.SetAdornerVerticalAlignment( _
    opacitySlider, _
    AdornerVerticalAlignment.OutsideTop)

' Position the adorner 5 pixels above the control. 
AdornerPanel.SetAdornerMargin( _
    opacitySlider, _
    New Thickness(0, 0, 0, 5))
// Setup the adorner panel.
// All adorners are placed in an AdornerPanel
// for sizing and layout support.
AdornerPanel myPanel = this.Panel;

// The slider extends the full width of the control it adorns.
AdornerPanel.SetAdornerHorizontalAlignment( 
    opacitySlider, 
    AdornerHorizontalAlignment.Stretch);

// Position the adorner above the control it adorns.
AdornerPanel.SetAdornerVerticalAlignment(
    opacitySlider, 
    AdornerVerticalAlignment.OutsideTop);

// Position the adorner 5 pixels above the control. 
AdornerPanel.SetAdornerMargin(
    opacitySlider, 
    new Thickness(0, 0, 0, 5));

Zooming Behavior

When the zoom setting for the designer view is changed to 200%, the adorned control is rendered at two times its size. All distances and fonts are larger, and lines are thicker. Many adorner designs specify that adorners remain their original size even when the designer view zoom changes.

DesignerView

The DesignerView class provides a collection of adorners and maps all user input to designer gestures. The DesignerView class derives from the Decorator class. It provides a visual surface for the designer. Assign the root element of the designer’s UI to the Child property of DesignerView and set the editing context property on the designer view to point to the editing context for the designer.

DesignerView view = new DesignerView();
view.Child = documentManager.View;
view.Context = editingContext;

The DesignerView class implements two aspects of the WPF Designer.

Adorners

The DesignerView class provides support for adorning elements in the view with additional visual adornments that overlay the controls being designed.

Input Routing

The DesignerView class routes user input to commands on adorners, tools, and tasks.

The DesignerView class works by introducing two additional elements in front of all content: an adorner layer and a hit-test layer. The following diagram shows the relationship of the designer view layers with the visual tree.

Designer View

The DesignerView class has an empty constructor for use in XAML.

See Also

Tasks

Walkthrough: Creating a Design-time Adorner

Reference

AdornerPanel

AdornerProvider

DesignerView

Other Resources

WPF Designer Extensibility