WPF added lot of flexibility and usability to the client application development. There are lots of features in WPF for enhancing the usability aspects of a client application. One of the interesting and very useful features is the WPF adorner. In this article we will discuss briefly about Adorner and how to create a simple adorner.
Adorner
Adorner is an extension to a UI element in WPF. WPF controls have an extra layer called AdornerLayer associated with it. We can add adorners or the decorators to this layer and display to the user in response to any event. Adorner can be a new custom control; can be template; or just a drawing over the current control
For our sample, I am using an adorner which will draw a rectangle and text.
Sample Adorner
Create an adorner class inherited from Adorner. Override the OnRender method for drawing the shapes and text. We can get access to the element that this adorner is bound to by using the AdornedElement property.
In our sample, I defined a Brush and Pen for drawing the rectangle and text. For drawing the rectangle, used the AdornerElement’s size.
public class MyAdorner : Adorner
{
public MyAdorner(UIElement adornedElement)
: base(adornedElement)
{
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
SolidColorBrush renderBrush=new SolidColorBrush(Colors.LightCoral);
Pen renderPen= new Pen(new SolidColorBrush(Colors.DarkBlue), 1.0);
drawingContext.DrawRectangle(renderBrush, renderPen,
new Rect(new Point(0, 0), AdornedElement.DesiredSize));
drawingContext.DrawText(new FormattedText("Help Text!", new CultureInfo("en-US"), FlowDirection.LeftToRight, new Typeface("Arial"), 18, Brushes.Black),
new Point(10,10));
}
}
User Control
For our sample, I have a small UserControl contains one Button.
<UserControl x:Class="WpfControlLibrary1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="41" d:DesignWidth="102" FontSize="16" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave">
<Grid Height="39" Width="98">
<Button Content="Hello !" Height="35" HorizontalAlignment="Left" Margin="0,4,0,0" Name="button1" VerticalAlignment="Top" Width="98"
FontWeight="Bold" FontSize="18" Foreground="#FF7A0000" />
</Grid>
</UserControl>
On UserControl’s MouseEnter event, created the Adorner for the button and add the same to the button’s AdornerLayer.
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
MyAdorner ad = new MyAdorner(button1);
AdornerLayer adLayer = AdornerLayer.GetAdornerLayer(button1);
adLayer.Add(ad);
}
On UserControl’s MouseLeave event, find all the adorners associated with the button and remove our custom adorner. We can have multiple adorners associated with a UI element.
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(button1);
if (adornerLayer != null)
{
Adorner[] adorners = adornerLayer.GetAdorners(button1);
if (adorners != null)
{
foreach (Adorner adorner in adorners)
{
if (typeof(MyAdorner).IsAssignableFrom(adorner.GetType()))
{
adornerLayer.Remove(adorner);
}
}
}
}
}
WPF Application
Create a WPF application and drag and drop our UserControl. Execute the application and observe the adorner displayed on Mouse enter event of UserControl.

When the mouse pointer is over the UserControl, adorner gets added to the AdornerLayer of the button.

Conclusion
Adorner is a light weight UI decorator, which will be added to the UIElement to extend the functionality. We can add multiple adorners to the UIElement depend on the requirements. Along with Adorners, we can have another exciting feature called HitTest, which will allow us to track the hit positions. We will discuss about the HitTest latter.