Custom Control Attributes

(March 2009 Issue)

Steve C Orr

October 30, 2009

11 Min Read
ITPro Today logo in a gray background | ITPro Today

Some hardcore developers prefer to write their code with Notepadrather than deal with the sometimes sluggish performance ofVisual Studio. However,the majority of .NET developers clearly appreciate the powerful interactivedesign-time development experience that Visual Studio can provide. To parlay thisrich experience into the realm of custom Web controls, control developersshould familiarize themselves with the key attributes that allow Visual Studioto do such impressive work.

 

Control Attributes

The code listed in Figure 1A should look rather ordinaryto developers who have created custom Web controls. The first line of codespecifies a design-time attribute that will be applied to the controldefinition that follows. As you can see, attributes are delimited by anglebrackets in VB.NET. In C#, attributes are instead delimited by square brackets,as is shown in Figure 1B.

")> _Public Class AttCtrl   Inherits WebControl       'TODO: implement control internals...End Class

Figure 1A: Here,the ToolboxData attribute decorates this control s class definition.

[ToolboxData("<{0}:AttCtrl runat=server>")]public class AttCtrl : WebControl{ //TODO: implement control internals...}

Figure 1B: Incontrast to VB.NET, attributes written in C# are delimited by square bracketsand do not require line-continuation characters.

To provide a consistent development experience, theToolboxData attribute must be attached to every custom Web control s classdefinition. The attribute s only parameter specifies the string that getsrendered to a Web form s ASPX definition each time application developers dragthe control onto a page from the Visual Studio toolbox.

Additionally, there are a few other common controlattributes often found decorating control definitions. For example, eachcontrol may optionally define one default event and property. Visual Studiokeys off these attributes to provide an optimized development experience forthe developers consuming the control. These attributes are summarized in Figure2, along with the ToolboxBitmap attribute, which can be used to customize thecontrol s Visual Studio toolbox icon.

Attribute Name

Description

DefaultEvent

Defines the control s most commonly consumed programmatic event (if any).

DefaultProperty

Defines the control s most commonly used design-time property (if any).

ToolboxData

Specifies the HTML tag that is generated when a new instance of the control is dragged from the toolbox onto a Web form.

ToolboxBitmap

Provided by the System.Drawing namespace as a way to specify the icon that should represent the control within the Visual Studio toolbox.

Figure 2: Commoncontrol attributes.

Niceties like this aren t strictly required in order tocreate a functional, reusable control that other developers find valuable. However,professional touches like these are what separates amateurs from professionals.

 

Property Attributes

Design-time attributes aren t limited to top-level controldefinitions. Each property exposed from within the control definition may alsobenefit from specially tuned design-time attributes. Figure 3 summarizes thedesign-time attributes most commonly applied to control properties.

Attribute Name

Description

Description

Used for describing the associated property.

Category

Specifies the category under which the associated property should appear in the Properties window.

Bindable

Enables/disables data-binding capabilities for the specified property.

Localizable

Enables/disables localization for the associated property.

DefaultValue

Specifies the property value that should be displayed when a custom value has not yet been set.

ReadOnly

Toggles the editability of the related property.

Browsable

When set to False, the associated property will not be displayed in the Properties window.

Obsolete

Provides a non-disruptive notification to consuming application developers that use of this property has been deprecated.

RefreshProperties

Commands the Properties window to fully refresh itself whenever the associated property value has changed.

MergableProperty

Allows the property to be changed in bulk when multiple instances of the control are selected.

UrlProperty

Enables invocation of the standard address chooser popup dialog box, which provides a more user friendly Web address selection experience.

NotifyParentProperty

Child properties can be configured to notify parent properties of any value modifications.

TypeConverter

Allows run-time conversion of value types.

DesignerSerializationVisibility

Configures the type of persistence that is applied upon serialization to the ASPX source document.

Figure 3: Common controlproperty attributes.

The Description attribute is used to provide additionaldetails about the intended use of the related property. The syntax is demonstratedin Figure 4.

 _Property Text() As String   Get       'TODO...   End Get   Set(ByVal Value As String)       'TODO...   End SetEnd Property

Figure 4: TheDescription attribute accepts a single string parameter.

When the property is selected in Visual Studio s Propertieswindow, the specified description is displayed at the bottom of that window. Figure5 illustrates this concept.


Figure 5: The value supplied by theDescription attribute gets displayed at the bottom of the Properties window.

The Category attribute can be used to group relatedproperties together in the Properties window. Commonly used property categoriesinclude Appearance, Behavior, and Data. For example, properties relating tocolors, styles, and fonts are typically grouped together under the Appearancecategory. Because developers now habitually look for properties underneaththese common categories, it is wise to place your custom properties in thesecategories, as well. However, there is nothing preventing the use of customcategories when the need arises. For example, the UserName property listed inFigure 6 will be grouped under a new custom category named User.

 _Property UserName() As String   Get       'TODO...   End Get   Set(ByVal Value As String)       'TODO...   End SetEnd Property

Figure 6: Multipleattributes may be applied to a single property, as long as they are separatedby commas.

Figure 6 also demonstrates how multiple attributes may beapplied to a single property, as long as all attributes are delineated bycommas. It also should be noted that the entire attribute definition list(along with the first line of the property definition) must be written as asingle logical line of code. This detail is inconsequential to C# developers,but to VB.NET developers it means making copious use of the line continuationcharacter ( _ ) to keep code readable.

The Bindable attribute is used to specify that theassociated property is a suitable target for data binding. If this attribute isexcluded (or it is explicitly set to False), then the property will not be ableto be programmatically manipulated via standard data binding techniques.

Localizable is another Boolean attribute that may beapplied to control properties. If a property is decorated with this attribute(and the value of True is supplied as its sole parameter), then that propertywill participate normally in all localization-related activities. Otherwise,the property will not be localized. For example, a property such as JobTitlewould likely make a good localization target, but attempts to localize aCustomerID property value would typically be an unnecessary waste of resources.

The DefaultValue attribute can be used to inform the Propertieswindow what to display when the underlying property value has not yet been set.The attribute s heavily overloaded parameter list provides great flexibility.

Some properties are meant to be referenced, but notaltered. Such properties can be decorated with the ReadOnly attribute, whichexpects a single Boolean parameter. Setting the ReadOnly design-time attributeto True will prevent the associated property from being modifiable in the Propertieswindow at design time. However, it should be noted that this attribute has noeffect on the run-time behavior of the property.

Some properties are relevant only under specificcircumstances. For example, a HitCounter property may provide valuable metricdata at run time, but at design time its value is moot. Therefore, it may bebest to hide the property at design time by setting its Browsable attribute toFalse. This will prevent the property from appearing in the Properties windowat design time, even though the property will be in place and fully functionalat run time.

 

Soothe Growing Pains

As applications evolve, business rules change andunderlying data structures often must be transformed to accommodate currentneeds. This may necessitate that preexisting control properties be added,deleted, or changed. Deleting an obsolete control property might sound harmlessat first, but consider what happens when the new version of the control isdeployed. Potentially, countless unsuspecting application developers may nolonger be able to compile because their existing code references a propertythat no longer exists. Suddenly, a simple upgrade turns into a show-stoppingintegration incident that distracts everyone from their usual duties.

A better approach is to leave the old field as-is for awhile, and provide a new property to support the new requirements. The oldproperty then can be decorated with the Obsolete attribute, and upgradeinstructions can be supplied as its parameter (see Figure 7). This will alloweverybody s applications to continue compiling and running normally, eventhough they ll get nagging compile-time warnings as long as their codecontinues to reference the deprecated property. As time permits, each applicationdeveloper will eventually modify their code to comply with the new standard,and the obsolete warnings will go away.

 _Property UserName() As String   Get       Return _userName   End Get   Set(ByVal Value As String)       _userName = Value   End SetEnd Property

Figure 7: Usingthe Obsolete attribute, deprecated properties can be eased out of productiongradually to avoid jarring disruptions.

 

Advanced Tips & Tricks

Sometimes a control s properties are related to each otherin deep and complex ways. Changing just a single property can trigger a cascadeof events that may affect the values of many other properties. After apotentially complicated sequence of events like this it can be difficult todetermine if the Properties window accurately reflects the current internalstate of the control. In such circumstances, the RefreshProperties attributecan come in handy (see Figure 8). Any time the value changes of a property that sbeen decorated with this attribute, the Properties window will refresh. Therefore,decorating each relevant property with this attribute should eliminate anyconcerns about the Properties window getting out of sync.

 _Property MyCustomProperty() As String...End Property

Figure 8: Exampleuse of the RefreshProperties and MergableProperty attributes.

By default, if an application developer selects threeinstances of your custom control and tries to set a property value for all ofthem at once, the attempt will fail. For complex scenarios where controlinstances may share interdependent state, this is a reasonable default. However,for simple scenarios (like setting a common background color for all selectedcontrols) it is good practice to allow the control consumer to edit as freelyas they desire. The solution is to decorate the custom property with theMergableProperty attribute (again, see Figure 8). This will successfully allowchanges to this property s value to propagate across each selected instance ofthe control.

Most property values can be displayed and manipulateddirectly in the Properties window. However, some kinds of data (like a seriesof charting data points) require more complex interactions than the simpleproperty grid can support. Even relatively simple data entry chores cansometimes benefit from a well designed popup dialog box to help speed thingsalong. For example, properties intended to hold URLs can benefit from theUrlProperty attribute. When a property decorated with this attribute isselected in the Properties window at design time, an ellipsis (...) button willappear. When clicked, the familiar dialog box shown in Figure 9 appears.


Figure 9: A single line of code isall it takes to invoke this common dialog box.

 

Conclusion

When it comes to creating and distributing custom Webcontrols, a little polish can go a long way. By decorating a control s classesand properties with design-time attributes, usability can be improved by leapsand bounds. Professional touches like these will make your control creationseasier to use, resulting in saved time and money for everyone involved. It justmakes good business sense.

Steve C. Orr is anASPInsider, MCSD, Certified ScrumMaster, Microsoft MVP in ASP.NET, and authorof Beginning ASP.NET 2.0 AJAX by Wrox. He sbeen developing software solutions for leading companies in the Seattle areafor more than a decade. When he s not busy designing software systems orwriting about them, he often can be found loitering at local user groups andhabitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.net or e-mail him at mailto:[email protected].

Read more about:

Microsoft
Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like