WPF Adorners Part 1 – What are adorners

WPF adorners are visuals that live in their own layer above the normal controls, they were originally designed to support adding notes inside the document viewer (that is why they’re in the System.Windows.Documents namespace) but they can be useful in many other situations.

In this series we will look at some ways to use adorners in an application and I will introduce a simple system to simplify the use of adorners.

Before we begin let’s look at a simple example:

We will create an adorner that draws four red boxes at it’s four corners:

using System;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows;

namespace AdornerDemo
{
    class FourBoxes : Adorner
    {
        public FourBoxes(UIElement adornedElement) :
            base(adornedElement)
        {
        }

        protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(0, 0, 5, 5));
            drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(0, ActualHeight-5, 5, 5));
            drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(ActualWidth-5, 0, 5, 5));
            drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(ActualWidth-5, ActualHeight-5, 5, 5));
        }
    }
}

You can see that adorners have a OnRender method you can override just like any other WPF visual – actually Adorner inherits from FrameworkElement and you can use every WPF feature you like inside adorners (more about that in a later post).

Another thing you can see is that an adorner is tied to a UIElement, it’s connected to this element in the constructor and remains connected to this element.

Now let’s use this adorner, we will start from the standard Window1 class and add a button and a Loaded event handler:

<Window x:Class="AdornerDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
    <Grid>
        <Button Content="Look at me" VerticalAlignment="Center" HorizontalAlignment="Center" Name="Btn"/>
    </Grid>
</Window>

And now we will attach our adorner to this button:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    AdornerLayer.GetAdornerLayer(Btn).Add(new FourBoxes(Btn));
}

You can see we use AdornerLayer.GetAdornerLayer to get the adorner layer, the adorner layer is the floating surface that adorners live in.

Once we have the layer we use AdornerLayer.Add and we’re done.

Important note: error checking was removed to make the sample easier to read, you should check the return value from AdornerLayer.GetAdornerLayer.

Now running our code we get:

In the next post in this series we will look into adding something a little more complex into the adorner layer.

posted @ Monday, June 21, 2010 11:18 AM

Comments on this entry:

# re: WPF Adorners Part 1 – What are adorners

Left by Ryan S Christensen at 9/6/2011 6:12 PM

the measurements are wrong in the FourBoxes Sample:

protected override void OnRender(DrawingContext drawingContext)
{
Rect adornedElementRect = new Rect(AdornedElement.DesiredSize);

drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(adornedElementRect.TopLeft.X, adornedElementRect.TopLeft.Y, 5, 5));
drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(adornedElementRect.BottomLeft.X, adornedElementRect.BottomLeft.Y - 5, 5, 5));
drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(adornedElementRect.TopRight.X - 5, adornedElementRect.TopRight.Y, 5, 5));
drawingContext.DrawRectangle(Brushes.Red, null, new System.Windows.Rect(adornedElementRect.BottomRight.X - 5, adornedElementRect.BottomRight.Y - 5, 5, 5));
}

Your comment:



 (will not be displayed)


 
 
 
Please add 2 and 6 and type the answer here: