WPF Adorner

Ambily.raj
Posted by in WPF category on for Beginner level | Points: 250 | Views : 52869 red flag
Rating: 5 out of 5  
 1 vote(s)

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.

 

Page copy protected against web site content infringement by Copyscape

About the Author

Ambily.raj
Full Name: Ambily KK
Member Level: Silver
Member Status: Member,Microsoft_MVP,MVP
Member Since: 5/18/2010 1:05:25 AM
Country: India
Thanks Ambily K K http://ambilykk.com/
http://ambilykk.com/
I have over 9 years of experience working on Microsoft Technologies. I am carrying the passion on Microsoft technologies specifically on web technologies such as ASP .Net and Ajax. My interests also include Office Open XML, Azure, Visual Studio 2010. Technology adoption and learning is my key strength and technology sharing is my passion.

Login to vote for this post.

Comments or Responses

Posted by: SheoNarayan on: 2/22/2011 | Points: 25
Excellent article Ambily, keep it up!

5 from me.
Posted by: Ambily.raj on: 2/22/2011 | Points: 25
Thanks SheoNarayan

Thanks
Ambily
Posted by: Madhu.b.rokkam on: 2/22/2011 | Points: 25
Very nice Article.. Keep it up.
Posted by: Tripati_tutu on: 2/22/2011 | Points: 25
Really nice article...
This will really helpful for us.

Thanks,
Tripati
Posted by: Ambily.raj on: 2/22/2011 | Points: 25
Thanks Madhu and Tripati

Regards
Ambily
Posted by: Anup1252000 on: 7/22/2011 | Points: 25
Great article.
Posted by: Revanthmachis on: 10/22/2011 | Points: 25
Hi Ambily, Thats simple way to say about adorner. Im a beginner for WPF and I understood about adorners in your beautiful article. But If you dont mind I need these adorners in someother way. I dont know if it is possible with adorners, but with your permission let me pose my issue here:
I have multiple shapes on canvas. I need to generate a bounding rectangle around all the selected shapes without altering their existing positions. And I should be able resize and rotate them as well. When i resize the whole group the scale should apply to all the shapes inside. Right now by using adorners, Im able to select multiple shapes and able to resize them at a time as well, but i dont have common bounding rectangle for those selected shapes.
Kindly post any ideas regarding the issue. Thanks in advance.
Revanth M

Login to post response

Comment using Facebook(Author doesn't get notification)