Design .Net

Designers, Controls And everything between them.

Create your own Designer or Introduction To Custom Designers - Part 1: Designer

Working with Winforms Designer and UserControls has always been a bit complicated, we could never get an easy access to the UserControls unique properties when designing our Control. We only had one option to access Properties via the Properties Window.

To understand better how Designers works please visit The Perfect Host.

In this post I will demonstrate how we can easily create and adapt a Custom Designer for a New UserControl

This figure demonstrate how a Button is Contained by a Form At RunTime.

When we are working In DesignTime each control we design has an Designer Attribute  attached to it.

For example this is how a Button Designer attribute is defined:

[Designer("System.Windows.Forms.Design.ButtonBaseDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), SRDescription("DescriptionButton"), ClassInterface(ClassInterfaceType.AutoDispatch), ComVisible(true)]

public class Button : ButtonBase, IButtonControl

{

In this example I have created a UserControl that contains a PictureBox. I may use this Control in many different Forms  or other UserControl. The main issue with my UserControl is that to access the PictureBox and define in each UserControl a different Image is a bit tricky. I can encapsulate the Image property from the PictureBox and use it as I uses my UserContol using the Properties Window.

The following example demonstrate how to access the Image Property from the PictureBox.

public class PictureDemoControl : UserControl

{

    private PictureBox pictureBox1;

    public Image PictureImage

    {

        get { return pictureBox1.Image; }

        set { pictureBox1.Image = value;}

    }

This is how we can edit the Image property using Properties Window:

fig04

This solution is nice but does not enable access to the Image property using anything other then Properties windows in Design-Time, beside that now the Image Property is accessible to all.

To avoid this we can create and define a new Designer for the user control, this designer will enable easy access in Design-Time.

Step 1: Create your own designer.

Your Designer should Inherit from ControlDesigner this will let you extend the basic Designer Behavior. Your custom ControlDesigner  will contain at least one Adorner, the designer should also initialize this services: IComponentChangeService, ISelectionService, BehaviorService. All this services are essential and will provide us access to the Designed Control.    

The Designer also contains Glyphs, Glyph is the UI that will be painted when your component is selected. Using the glyph you can basically manipulate and design your Control in Design-Time. I strongly recommend that you will not use Adorner for each one of your Glyphs - that may be too costly. Try dividing your Glyphs into logical groups and then assign each group with a different Adorner .

This is how your Designer Class should look like:

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]

    internal class MyPictureDesigner : ControlDesigner

    {

        // This adorner holds the glyphs

        private Adorner m_pictureSelectorAdorner = null;

        // References to designer services

        private IComponentChangeService m_componentChangeService = null;

        private ISelectionService m_selectionChangeService = null;

        private BehaviorService m_behaviorService = null;

        private void InitializeServices()

        {

            // Reference to IComponentChangeService.

            this.m_componentChangeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;

            //Reference  to ISelectionService.

            this.m_selectionChangeService = GetService(typeof(ISelectionService)) as ISelectionService;

            //Reference  to BehaviorService.

            this.m_behaviorService = GetService(typeof(BehaviorService)) as BehaviorService;

            this.m_pictureSelectorAdorner = new Adorner();

            this.m_behaviorService.Adorners.Add(this.m_pictureSelectorAdorner);

        }

        public override void Initialize(IComponent component)

        {

            base.Initialize(component);

            InitializeServices();

            /*this is where we will Assign the Adorner with Glyph*/

More about Glyphs and Behavior at Part 2.

Happy New Year!

Comments

Yaniv said:

Real professional article.

keep on the good work.

i realy learned alot...

# January 3, 2008 2:01 PM

Yogev said:

Thank you!

In the next few posts I will try to cover the basics in Extending Designer subject.

# January 4, 2008 1:13 AM

Introduction to custom designers « WPF, .NET & Other stuff said:

Pingback from  Introduction to custom designers « WPF, .NET & Other stuff

# January 17, 2008 11:54 AM

TrackBack said:

# August 27, 2008 6:16 AM

TrackBack said:

# August 27, 2008 6:16 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: