The AdornerLayer is the parent of all the Adorners of a Visual.
The Adorners added to the AdornerLayer of the Visual have a z-order that make them the top elements.
Button button = new Button();
button.Content = "Click me!";
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(button);
Adorner adorner = new MyAdorner(button);
adornerLayer.Add(adorner);
By being on top, the Adorner receives focus and input before the adorned Visual, making it the perfect for manipulating the adorned visual:
- Move or resize it, transform it;
- Add visual feedback on top of it like notes or icons;
- Filter input from it;
- …
The Adorner class is provided to provide basic support for adorners.
A custom adorner derives from Adorner and adds value.
public class ResizingSelection : Adorner
{
public ResizingSelection(UIElement adornedElement)
: base(adornedElement)
{
}
}
The Adorner class does not provide any rendering behavior.
This means that the rendering has to be provided by:
- Overriding OnRender and issuing commands to the DrawingContext;
- Or by providing a visual collection to it.
The following example shows the 2nd approach.
Any Visual may be added with approach and, using the adorned element characteristics, the adorner’s Visuals may be setup so that they surround the adorned element, like in this ResizeSelection adorner.
public class ResizingSelection : Adorner
{
VisualCollection _visualChildren;
public ResizingSelection(UIElement adornedElement)
: base(adornedElement)
{
_visualChildren = new VisualCollection(this);
_visualChildren.Add(…);
}
protected override int VisualChildrenCount { get { return _visualChildren.Count; } }
protected override Visual GetVisualChild(int index) { return _visualChildren[index]; }
}
Since the Adorner absorbs the input from the adorned element, by sitting on top, in order for the adorned element to receive input, the Adorner must do one of 2 things:
- Propagate the input events to the element;
- The alternative is to indicate that the input must be passed through to the element.
IsHitTestVisible = false;
Finally, there is a prebuilt implementation of an Adorner (Adorner is abstract) meant for styling the adorned element.
This class is AdornerDecorator:
- It receives the element to adorn;
- It has a Child property that is supposed to be the root of the visual tree sitting on top of the adorned element;
- It supports a single child.