Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating Custom Controls-Providing Design Time Support 1

0.00/5 (No votes)
22 Feb 2005 1  
This article explains how to develop customized design time extensions.

Introduction

During my interactions in the C# Forum, I came across questions on providing Design time support for custom controls. So I thought of sharing a little experience I have on this.

The Design time support architecture allows us to develop customized design time extensions using which we can configure our controls/properties of the control. Ex: Dock, Anchor properties of Button and other controls. I also encountered a similar scenario while developing a custom user control, where I needed to provide User Interface for modifying its property at design time.

Let's see in brief the .NET FrameWork support for this.

.NET Support

The .NET FrameWork has interfaces that we can use to implement customized design time support. There are three ways in which we can provide this.

  • UITypeEditor
  • TypeConverters
  • Designers

UITypeEditors:

UITypeEditors allow us to provide a custom user interface for editing the value of a property of the control. This also allows us to display the visual representation of the current value in the properties window.

TypeConverters:

TypeConverters allow us to convert the values between the types. They also allows us to provide logic for configuration of a property in the property browser.

Designers:

Designers allow us to customize the behaviour of our control at design time.

This article explains how we can use UITypeEditors and TypeConverters, to provide design time support. Using Designers are explained in the next article.

Using UITypeEditor/Property Editor

Dock, Anchor properties of .NET controls provide user interface for supplying/setting their value. These are called as Property Editors. We can use .NET FrameWork UITypeEditor class to create such interfaces for our custom properties. Property Editors are generally displayed in the drop-down area inside the properties window itself. But we can also make them to appear as modal windows.

Let's see how we can create Property Editors for our custom properties. We will use a custom control (Rectangle Control) for explaining this. Rectangle Control draw a filled rectangle. This control exposes two custom properties, RectWidth and RectHeight. Users can use these properties for setting width and height of the rectangle.

It will be more useful if we can provide a user interface (TrackBar) for supplying these values instead of asking the users to enter the values.

Sample screenshot

Fig 1: Property Editor for Setting RectHeight and RectWidth

The first step in creating the property editor is to specify the editor (WidthEditor) in the Editor attribute associated with the property procedure.

[Description("Width of the rectangle"),Editor(typeof(WidthEditor),
                                                        typeof(UITypeEditor))]
public int RectWidth
{
    get{
        return this.width;
    }
    set{
        if( value > 0){
            this.width = value;
            this.Invalidate();
          }
    }
}

The Editor attribute takes two System.Type arguments. The first argument is the type of editor. (WidthEditor - we will be creating this in the second step). The second argument is always typeof(UITypeEditor).

In the second step we have to create WidthEditor class. This class should be inherited from System.Drawing.Design.UITypeEditor class and must override two methods. They are GetEditStyle() and EditValue() methods.

The form designer calls GetEditStyle() method when it's filling the properties window with the values of all the properties of the control. This method returns an enumerated value that tells the designer whether the property editor is going to display in the drop-down area or modal form. In our example the property editor is displayed in the drop-down area.

public override UITypeEditorEditStyle 
GetEditStyle(System.ComponentModel.ITypeDescriptorContext 
context)
{
    return 
    UITypeEditorEditStyle.DropDown;
}

The form designer calls the EditValue() method when the user clicks the button beside the property name. The EditValue() method creates TrackBar control and sets the configuration details for it. (Like Range, Orientation). This method uses IWindowsFormEditorService class object to show the TrackBar control in the drop-down area.

IWindowsFormsEditorService frmsvr = 
(IWindowsFormsEditorService)provider.GetService(
                           typeof(IWindowsFormsEditorService));
frmsvr.DropDownControl(tbr); //tbr = Object of Type track 

bar

That's all we need to do. Now we can use this control by adding it to the from designer. (The attached solution has TestCustomControl project which consumes this control). When we select RectWidth or RectHeight properties, a TrackBar control will be displayed. The values of these properties can be changed using the TrackBar. When we change these values, the new value will appear in the property browser and rectangle will be redrawn with the current dimension . Very simple. Am I right?

If we want to display the modal form instead of showing it in drop-down area, we need to follow the same steps with only two differences.

  1. Return value of GetEditStyle()should be UITypeEditorEditStyle.Modal.
  2. We need to create a Form class and should add all the controls that make up the editor interface to this Form. In the EditValue() method we need to create an instance of this form. Now to show this form we need to call ShowModal() method of IWindowsFormsEditorService class.

Let's move into the second topic of this article. Using TypeConverters.

Using TypeConverters

We know that few properties (Font, Size) return objects instead of scalar values and these properties are displayed in the property browser with a "+" sign. If our custom control contain any properties that return .NET FrameWork defined objects (Font, Point, Location, Size) then they will inherit the similar behaviour. But if our custom control contains any property that returns a custom object, then how can we achieve the similar behaviour? To get that, we need to create a custom TypeConverter class.

Fig2: PhoneData property returning a custom object

Fig2:PhoneData property with "+" sign

The current example use PhoneNumber custom control. This control allows the users to enter Name, CountryCode, AreaCode, PhoneNumber details. Let's expose this data in a single property instead of exposing them in five different properties.

The first step in doing this is to create PhoneNumber class that wrap all the properties and raise PropertyChanged event when any property changes. We need to decorate this class with TypeConverter attribute.

[TypeConverter(typeof(PhoneTypeConverter))]
public class PhoneNumber
{
}

TypeConverter attribute tells the form designer that PhoneTypeConverter is associated with PhoneNumber class.

In the second step we need to create PhoneTypeConverter class which is derived from System.ComponentModel.TypeConverter and override two methods. They are GetPropertiesSupported(), GetProperties() methods.

GetPropertiesSupported() method returns whether the object supports properties or not. Form designer use this value to display "+" symbol at PhoneData property. Since our object supports properties GetPropertiesSupported() method returns true value.

GetProperties() method returns PropertiesDescriptorCollection object which will describe the items that will appear when the "+" symbol is clicked.

public override PropertyDescriptorCollection 
GetProperties(ITypeDescriptorContext context, 
               object value, Attribute[] attributes)
{
return 
TypeDescriptor.GetProperties(typeof(PhoneNumber));
}

The third and last step is to set the DesignerSerializationVisibility attribute of the PhoneData to Content.

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

DesignerSerializationVisibility attribute specify the type of persistence to use while serializing a property on a control at design time. Setting this value to content tells VS.NET that, it should serialize the contents of this PhoneData property.

Now it's the time for compiling and using the control. When we add this control to the form designer the PhoneData property of the PhoneNumber control appear with "+" sign in the properties window. Clicking on the "+" sign will expand all the items. When we modify any value it will be displayed in the PhoneNumber control.

Conclusion

In this article we saw how we can use PropertyEditor and TypeConverters for enhancing design time support of our custom controls. In the next article we will see how we can use designers.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here