Creating custom controls is a key technique in .NET development. This article by Matthew is the first of a two part series where he looks at how to create a custom Windows Form control that behaves properly in Visual Studio .NET.
Custom Controls and Design-Time Support: Part 1/2 - Attributes (Page 4 of 5 )
The next step in improving the DirectoryTree control is adding designer attributes. These attributes instruct the IDE how to treat various parts of your control. To specify this type of information about a custom control in another programming language, you would either need to create a separate file in a proprietary format, or use some sort of visual tool. With attributes, the information that describes your control can be easily created and edited alongside your code, but it is still cleanly separated from the logic that generates the user interface.
You may have noticed that the DirectoryTree.Drive property appears in the design window grouped under the generic "Misc" category, without any additional information. You can improve on this situation using attributes. The example below adds a Description, Category, and DefaultValue attribute to the Value property. Note that when you use more than one attribute, they are all enclosed between square brackets, and separated with commas. The underscore character is used to spread the attributes over several lines for better readability.
[Category("Appearance"), Description("A letter representing the drive the DirectoryTree will use.")] public char Drive
All of these attributes are found in the System.ComponentModel namespace, along with many more that allow you to configure various aspects of your control's design-time behavior. The table below lists some of the most useful attributes you can use to configure properties.
If False, indicates that a property should not be shown in the Properties window. However, the property will still be accessible through code.
Sets the category under which the property will appear in the Properties window. If a category with this name doesn't exist, it will be created.
Sets the initial value that will be used for this property when the control is created.
Specifies the text description that will be displayed for this property in the Object Browser of Properties window.
When set to True, this property will only be available at design time. This is typically used with special properties that configure how a control behaves at design time (like a SuppressUI property), and don't correspond to a "real" piece of information about the control.
When set to True on an object property, this attribute ensures that the sub-properties of this object will be displayed as read-only. For example, if you apply this to a property that uses a Point object, the X and Y sub-property will be read-only.
When set to True, the design-time value for this property will be stored in a resource file, instead of in the generated code. This makes it easy to swap the value later by introducing a new resource file. When the user configures properties that don't use this attribute, the appropriate code will be inserted in the hidden designer region of the form, unless it requires a special data type (like an image) that must be stored in a resource file.
Set this to True to indicate that a parent property should receive notification about changes to the property's value (and update its display accordingly). For example, the Size property has two nested properties: Height and Width. These nested properties should be marked with this attribute.
When True, indicates that the property should be displayed with brackets around it in the Properties window (like the Name property).
When True, this property is read-only in the Properties window at design time.
You use this attribute with a value from the RefreshProperties enumeration. It specifies whether the rest of the Properties window must be updated when this property is changed (for example, if one property procedure could change another property).
A few attributes can be applied to your custom control class declaration, rather than a specific property. These include two attributes that set the default event and property. Here's how we could use these attributes with the DirectoryTree:
[DefaultEvent("DirectorySelected"), DefaultProperty("Drive")] public class DirectoryTree : TreeView
When the application programmer double-clicks on your control, Visual Studio .NET will automatically add an event handler for the default event.
The DefaultProperty is the property that is highlighted in the Properties window by default, the first time the control is selected.