Data Types and UITypeEditors
The Properties window does a solid job of providing support for all common data types. Basic data types like strings and numbers are all seamlessly supported. If you create a property that uses a custom enumeration, the Properties window automatically provides a drop-down list with the values from the enumeration.
For example, consider the DisplayStyle property shown here:
public enum Display
{
Standard,
SpecialDirectoryPictures,
AllDirectoryPictures
}
private Display displayStyle;
public Display DisplayStyle
{
get
{
return displayStyle;
}
set
{
displayStyle = value;
}
}
The enumerated values are shown in the Properties window (see Figure 8-15).

Figure 8-15: Enumerations in the Properties window
Note
Remember, even if you use an enumerated value, you still need to perform some error-checking in your property procedure. Though programmers won't be able to submit an invalid value through the Properties window, nothing prevents them from using code to directly set an integer value that doesn't correspond to a valid value in the enumeration.In addition to this basic level of support, you may have noticed that some richer object types have additional design-time support. For example, if you create a Property that has a Font or Color data type, a special color picker or font selection dialog is used in the Properties window. Similar magic happens if you create a Collection property. This support is provided through .NET UITypeEditor classes, which are special components that provide the design-time user interface that allows the programmer to set complex properties.
Using Prebuilt UITypeEditors
The base UITypeEditor class is found in the System.Drawing.Design namespace. You can inherit from this class to create your custom UITypeEditors, or you can use one of the derived classes that are provided with the .NET framework. These classes are listed in Table 8-5 (UITypeEditors that are only usable with specific web controls have been omitted).
Table 8-5: UITypeEditors in the .NET Framework
ClassDescription
System.ComponentModel.Design.ArrayEditorEdits an array by allowing the programmer to enter a list of strings. Used automatically for supported arrays.
System.Drawing.Design.FontEditorAllows the programmer to select and configure a font. Used automatically for font properties.
System.Drawing.Design.ImageEditorAllows the programmer to create an Image object by selecting a bitmap from an open file dialog. Used automatically for image types.
System.Web.UI.Design.WebControls.RegexTypeEditorAllows the programmer to choose a regular expression from a list of common choices. This UITypeEditor works with string properties.
System.Windows.Forms.Design.AnchorEditorAllows the Anchor property to be set at design time.
System.Windows.Forms.Design.FileNameEditorAllows a fully qualified filename to be set by choosing a file from an open file dialog box. This UITypeEditor works with string properties.
Depending on the data type of your property, .NET may use the corresponding UITypeEditor automatically (for example, with a Font). On the other hand, some UITypeEditors do not have dedicated types. An example is the RegExTypeEditor, which allows the programmer to choose a common regular expression for a control property. The regular expression is stored as an ordinary string, so it needs to be explicitly associated with the appropriate UITypeEditor.
You associate a property with a UITypeEditor using the Editor attribute. Consider this example:
private string regEx = ";
[Editor(typeof(System.Web.UI.Design.WebControls.RegexTypeEditor),
typeof(UITypeEditor))]
public string ValidationExpression
{
get
{
return regEx;
}
set
{
regEx = value;
}
}
When the programmer clicks this property in the Properties window, an ellipsis (…)appears next to the property name. If the programmer clicks the ellipsis button, a full dialog appears with common regular expression choices (see Figure 8-16).

Figure 8-16: The RegexTypeEditor
Note
Interestingly, this type editor is originally designed for the validation controls provided with ASP.NET, and is provided alongside the web controls in the .NET namespaces. However, it works equally well with a Windows control.
Custom UITypeEditors
You can also develop custom UITypeEditor classes to allow special settings to be configured. For example, consider the TreeView control. Its Nodes property is a collection, but it doesn't use the standard collection editor (which only allows strings to be entered). Instead, it uses its specialized UITypeEditor.
To create a custom type editor, you must first create a class that derives from System.Drawing.Design.UITypeEditor. You can then override the four methods shown in Table 8-6.
Table 8-6: UITypeEditor Overridable Methods
ClassMethodDescription
EditValue()Invoked when the property is edited. Generally, this is where you would create a special dialog box for property editing.
GetEditStyle()Specifies whether the type editor is a DropDown (provides a list of specially drawn choices), Modal (provides a dialog box for property selection), or None (no editing supported).
GetPaintValueSupported()Use this to return true if you are providing a PaintValue() implementation.
PaintValue()Invoked to paint a graphical thumbnail that represents the value in the property grid.
The PaintValue() supported technique requires a little GDI+ wizardry, and you consider an example that uses it in Chapter 13. The next example, however, uses the EditValue() method with the DirectoryTree control. It allows editing of the Drive property by presenting the dialog box developed earlier.
public class DriveEditor : UITypeEditor
{
public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(
System.ComponentModel.ITypeDescriptorContext context)
{
// We will use a window for property editing.
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(
System.ComponentModel.ITypeDescriptorContext context,
System.IServiceProvider provider, object value)
{
SelectDrive frm = new SelectDrive();
// Set current drive in window.
frm.DriveSelection = (char)value;
frm.ShowDialog();
// Return the new value.
return frm.DriveSelection;
}
public override bool GetPaintValueSupported(
System.ComponentModel.ITypeDescriptorContext context)
{
// No special thumbnail will be shown for the grid.
return false;
}
}
The type editor is attached to the appropriate property using an Editor attribute:
[Editor(typeof(DriveEditor), typeof(UITypeEditor))]
public Char Drive
One benefit to this design is that you can reuse this UITypeEditor with any drive property in any control. It's specific to the property data type, not the control.
An alternative approach is to use a DirectoryInfo object to represent the drive instead of an underlying char. Because the property editing is now handled by the UITypeEditor, there's no need to choose a basic type that can be edited with the default design-time support built into the property grid. That would also give you the freedom to enhance the control so it could be set to initially display a specific subdirectory, for example.