Online courses in ASP.NET MVC, ASP.NET Core, and Design Patterns conducted by Bipin Joshi. Read more...
Learn ASP.NET MVC, ASP.NET Core, and Design Patterns through our online training programs. Courses conducted by Bipin Joshi on weekends. Read more details here.

Design Custom Editor for a Property

Introduction

In the previous article we discussed type converters. Type converters come handy when you want to accept property values in plain text form. However, at times you may not want to allow the user to enter text values directly. You may want to present a custom value picker in the form of a dropdown control or a dialog box. This is possible with the help of Type Editors and this article examines them with an example.

Type Editors

A type editor is a class that derives from UITypeEditor base class and provides a way to pick up property value from a custom dropdown control or dialog box. There are certain type converter classes that are inbuilt to the .NET framework. For example, when you create any property that is of type Color or Font the property window automatically displays appropriate value picker controls (see figure below).

Some of the common inbuilt type editors are:

  • FontEditor
  • ColorEditor
  • DateTimeEditor
  • FileNameEditor
  • FolderNameEditor
  • MultilineStringEditor

Using inbuilt type editors

Let's see a simple example that illustrates how you can consume the inbuilt type editors listed above. To work through the example you need to create a custom control class library with a class named SimpleControl. The class contains two three properties viz. Text, SourceFile and SourceFolder. The complete source code of the class is shown below:

public class SimpleControl : WebControl
{
public string Text
{
get
{
return ViewState["Text"] as string;
}
set
{
ViewState["Text"] = value;
}
}

public string SourceFile
{
get
{
return ViewState["SourceFile"] as string;
}
set
{
ViewState["SourceFile"] = value;
}
}

public string SourceFolder
{
get
{
return ViewState["SourceFolder"] as string;
}
set
{
ViewState["SourceFolder"] = value;
}
}
}

The class and properties are fairly straightforward. What we would like to do is:

  • The Text property should open a multiline text entry region rather than normal single line editor
  • The SourceFile property should open a file open dialog box in the property window
  • The SourceFolder property should open a folder selector dialog box in the property window

As you might have guessed these type editors are inbuilt into the .NET framework and all we need to do is attach them to the respective properties. A type editor is attached to a property using [Editor] attribute. The usage of this attribute is shown below:

[Editor(<editor_class_type_info>),
<base_class_type_info>)]

The first parameter to the [Editor] attribute is the type information (Type instance) of the class that is being attached as a type editor and the second parameter is the type information of the base class of the type editor.

For the sake of our example decorate the Text, SourceFile and SourceFolder properties with the [Editor] attribute as shown below:

[Editor(typeof(MultilineStringEditor), 
typeof(UITypeEditor))]
[Editor(typeof(FileNameEditor), 
typeof(UITypeEditor))]
[Editor(typeof(FolderNameEditor), 
typeof(UITypeEditor))]

If you consume the SimpleControl on a web form you will notice that the SourceFile and SourceFolder properties show ellipses in the property window. Clicking on the ellipses open a file open dialog and folder selector dialog respectively.

The Text property shows a multiline text entry region.

Creating custom type editor

A type editor normally comes in two flavors viz. dropdown and dialog. In order to create a custom type editor you need to follow these steps:

  • Create custom value picker
    • If you want a dropdown value picker then create a custom windows forms control representing the UI of the value picker
    • If you want a dialog from which the user should pick the value then create a windows form with the required UI
  • Create a custom type editor class that inherits from UITypeEditor base class ad override certain methods
  • Create a custom control that will consume your type editor
  • Mark one or more properties of the custom control to use the custom type editor

As an example we will create a dropdown type editor for selecting predefined color values and a dialog based type editor for accepting a property value. We will call them as ColorTypeEditor and TagTypeEditor respectively.

By convention type editor classes are named as XXXXTypeEditor where XXXX is the data type they deal with.

Creating windows custom control and form

Add a new project of type Windows Forms Control Library to the existing solution. Rename the default control to ColorDropDown. Drag and drop a combo box on it and add three fixed color values namely Red, Blue and Yellow.

The control will have SelectedValue property as shown below:

public Color SelectedValue
{
get
{
switch (comboBox1.SelectedIndex)
{
case 0:
return Color.Red;
break;
case 1:
return Color.Blue;
break;
case 2:
return Color.Yellow;
break;
default:
return Color.Blue;
}
}
}

The SelectedValue property simple returns a Color value depending on the selection.

Now add a new Windows Form to the project and design it as shown below:

The form consists of a textbox and two buttons. Set the DialogResult property of the OK and Cancel buttons to Ok and Cancel respectively. The windows form contains Value property that simply returns value entered in the textbox.

public string Value
{
get
{
return textBox1.Text;
}
}

Creating custom type editor class

Now add a new class to the web control class library (where you created SimpleControl class) named ColorTypeEditor and inherit it from UITypeEditor base class.

In the ColorTypeEditor class we need to override certain base class methods. The first method being GetEditStyle().

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

The GetEditStyle() method governs whether we want dropdown value picker or a dialog box. The UITypeEditorEditStyle enumeration has three values viz. DropDown, Modal and None. For the ColorTypeEditor we want to display a dropdown with fixed color values to pick from and hence we return editor style as DropDown.

The second method to be overridden is EditValue() and is shown below:

public override object EditValue
(ITypeDescriptorContext context, 
IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorservice = null;
if (provider != null)
{
editorservice = (IWindowsFormsEditorService)
provider.GetService(typeof
(IWindowsFormsEditorService));
}
if (editorservice != null)
{
ColorDropDown editor = new ColorDropDown();
editorservice.DropDownControl(editor);
return editor.SelectedValue;
}
else
{
return value;
}
}

The EditValue() method returns the selected value from the dropdown or dialog to the property window. It first gets a reference to what is called as windows forms editor service and then calls DropDownControl() method by passing an instance of the windows custom control we created earlier. This way the property window will present that control to the user while editing the property value. Finally the SelectedValue from the ColorDropDown control is returned to the caller.

Properties such as Color and Font show a preview of the selected value in a small rectangle followed by the actual value. To accomplish this you need to override two more methods namely GetPaintValueSupported() and PaintValue(). The GetPaintValueSupported() should return true if you want to implement this feature. The PaintValue() method actually draws the preview rectangle. For ColorTypeEditor these two methods are implemented as follows:

public override bool GetPaintValueSupported
(ITypeDescriptorContext context)
{
return true;
}

public override void PaintValue
(PaintValueEventArgs e)
{
WebControl c = e.Context.Instance 
as WebControl;
e.Graphics.FillRegion(new SolidBrush
(c.BackColor), new Region(e.Bounds));
base.PaintValue(e);
}

The PaintValue() method simply draws a filled region with the appropriate color using the Graphics object.

Next, add a type editor class for TagTypeEditor. The TagTypeEditor class will override only the first two methods as shown below:

public override UITypeEditorEditStyle 
GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}

public override object EditValue
(ITypeDescriptorContext context, 
IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorservice = null;
if (provider != null)
{
editorservice = (IWindowsFormsEditorService)
provider.GetService(typeof(
IWindowsFormsEditorService));
}
if (editorservice != null)
{
TagDialog editor = new TagDialog(
value.ToString());
editorservice.ShowDialog(editor);
return editor.Value;
}
else
{
return value;
}
}

The code shown above is similar to the previous case except with few differences. Notice the lines marked in bold characters. This time we set the editor style to Modal i.e. dialog box and use ShowDialog() method passing an instance of the Windows Form.

Consuming type editors in custom control

Now that our custom type editors are ready we can consume them in SimpleControl. Add two properties to the SimpleControl as shown below:

[Editor(typeof(ColorTypeEditor), 
typeof(UITypeEditor))]
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
}
}

[Editor(typeof(TagTypeEditor), 
typeof(UITypeEditor))]
public string Tag
{
get
{
return ViewState["tag"] as string;
}
set
{
ViewState["tag"] = value;
}
}

Notice how the [Editor] attribute is used to attach our custom type editors with the properties.

The following screen shots show how the custom type editors look like in the property window.




Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 30 Mar 2008



Tags : ASP.NET Custom Controls