Some hardcore developers prefer to write their code with Notepad
rather than deal with the sometimes sluggish performance ofVisual Studio
. However,
the majority of
.NET developers
clearly appreciate the powerful interactive
design-time development experience that Visual Studio can provide. To parlay this
rich experience into the realm of custom Web controls, control developers
should familiarize themselves with the key attributes that allow Visual Studio
to do such impressive work.
The code listed in Figure 1A should look rather ordinary
to developers who have created custom Web controls. The first line of code
specifies a design-time attribute that will be applied to the control
definition that follows. As you can see, attributes are delimited by angle
brackets in VB.NET. In C#, attributes are instead delimited by square brackets,
as is shown in Figure 1B. Figure 1A: Here,
the ToolboxData attribute decorates this control s class definition. Figure 1B: In
contrast to VB.NET, attributes written in C# are delimited by square brackets
and do not require line-continuation characters. To provide a consistent development experience, the
ToolboxData attribute must be attached to every custom Web control s class
definition. The attribute s only parameter specifies the string that gets
rendered to a Web form s ASPX definition each time application developers drag
the control onto a page from the Visual Studio toolbox. Additionally, there are a few other common control
attributes often found decorating control definitions. For example, each
control may optionally define one default event and property. Visual Studio
keys off these attributes to provide an optimized development experience for
the developers consuming the control. These attributes are summarized in Figure
2, along with the ToolboxBitmap attribute, which can be used to customize the
control 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: Common
control attributes. Niceties like this aren t strictly required in order to
create a functional, reusable control that other developers find valuable. However,
professional touches like these are what separates amateurs from professionals. Design-time attributes aren t limited to top-level control
definitions. Each property exposed from within the control definition may also
benefit from specially tuned design-time attributes. Figure 3 summarizes the
design-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 control
property attributes. The Description attribute is used to provide additional
details about the intended use of the related property. The syntax is demonstrated
in Figure 4. Figure 4: The
Description attribute accepts a single string parameter. When the property is selected in Visual Studio s Properties
window, the specified description is displayed at the bottom of that window. Figure
5 illustrates this concept. The Category attribute can be used to group related
properties together in the Properties window. Commonly used property categories
include Appearance, Behavior, and Data. For example, properties relating to
colors, styles, and fonts are typically grouped together under the Appearance
category. Because developers now habitually look for properties underneath
these common categories, it is wise to place your custom properties in these
categories, as well. However, there is nothing preventing the use of custom
categories when the need arises. For example, the UserName property listed in
Figure 6 will be grouped under a new custom category named User. Figure 6: Multiple
attributes may be applied to a single property, as long as they are separated
by commas. Figure 6 also demonstrates how multiple attributes may be
applied to a single property, as long as all attributes are delineated by
commas. It also should be noted that the entire attribute definition list
(along with the first line of the property definition) must be written as a
single logical line of code. This detail is inconsequential to C# developers,
but to VB.NET developers it means making copious use of the line continuation
character ( _ ) to keep code readable. The Bindable attribute is used to specify that the
associated property is a suitable target for data binding. If this attribute is
excluded (or it is explicitly set to False), then the property will not be able
to be programmatically manipulated via standard data binding techniques. Localizable is another Boolean attribute that may be
applied to control properties. If a property is decorated with this attribute
(and the value of True is supplied as its sole parameter), then that property
will participate normally in all localization-related activities. Otherwise,
the property will not be localized. For example, a property such as JobTitle
would likely make a good localization target, but attempts to localize a
CustomerID property value would typically be an unnecessary waste of resources. The DefaultValue attribute can be used to inform the Properties
window 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 not
altered. Such properties can be decorated with the ReadOnly attribute, which
expects a single Boolean parameter. Setting the ReadOnly design-time attribute
to True will prevent the associated property from being modifiable in the Properties
window at design time. However, it should be noted that this attribute has no
effect on the run-time behavior of the property. Some properties are relevant only under specific
circumstances. For example, a HitCounter property may provide valuable metric
data at run time, but at design time its value is moot. Therefore, it may be
best to hide the property at design time by setting its Browsable attribute to
False. This will prevent the property from appearing in the Properties window
at design time, even though the property will be in place and fully functional
at run time. As applications evolve, business rules change and
underlying data structures often must be transformed to accommodate current
needs. This may necessitate that preexisting control properties be added,
deleted, or changed. Deleting an obsolete control property might sound harmless
at first, but consider what happens when the new version of the control is
deployed. Potentially, countless unsuspecting application developers may no
longer be able to compile because their existing code references a property
that no longer exists. Suddenly, a simple upgrade turns into a show-stopping
integration incident that distracts everyone from their usual duties. A better approach is to leave the old field as-is for a
while, and provide a new property to support the new requirements. The old
property then can be decorated with the Obsolete attribute, and upgrade
instructions can be supplied as its parameter (see Figure 7). This will allow
everybody s applications to continue compiling and running normally, even
though they ll get nagging compile-time warnings as long as their code
continues to reference the deprecated property. As time permits, each application
developer will eventually modify their code to comply with the new standard,
and the obsolete warnings will go away. Figure 7: Using
the Obsolete attribute, deprecated properties can be eased out of production
gradually to avoid jarring disruptions. Sometimes a control s properties are related to each other
in deep and complex ways. Changing just a single property can trigger a cascade
of events that may affect the values of many other properties. After a
potentially complicated sequence of events like this it can be difficult to
determine if the Properties window accurately reflects the current internal
state of the control. In such circumstances, the RefreshProperties attribute
can come in handy (see Figure 8). Any time the value changes of a property that s
been decorated with this attribute, the Properties window will refresh. Therefore,
decorating each relevant property with this attribute should eliminate any
concerns about the Properties window getting out of sync. Figure 8: Example
use of the RefreshProperties and MergableProperty attributes. By default, if an application developer selects three
instances of your custom control and tries to set a property value for all of
them at once, the attempt will fail. For complex scenarios where control
instances may share interdependent state, this is a reasonable default. However,
for simple scenarios (like setting a common background color for all selected
controls) it is good practice to allow the control consumer to edit as freely
as they desire. The solution is to decorate the custom property with the
MergableProperty attribute (again, see Figure 8). This will successfully allow
changes to this property s value to propagate across each selected instance of
the control. Most property values can be displayed and manipulated
directly in the Properties window. However, some kinds of data (like a series
of charting data points) require more complex interactions than the simple
property grid can support. Even relatively simple data entry chores can
sometimes benefit from a well designed popup dialog box to help speed things
along. For example, properties intended to hold URLs can benefit from the
UrlProperty attribute. When a property decorated with this attribute is
selected in the Properties window at design time, an ellipsis (...) button will
appear. When clicked, the familiar dialog box shown in Figure 9 appears. When it comes to creating and distributing custom Web
controls, a little polish can go a long way. By decorating a control s classes
and properties with design-time attributes, usability can be improved by leaps
and bounds. Professional touches like these will make your control creations
easier to use, resulting in saved time and money for everyone involved. It just
makes good business sense. Steve C. Orr is an
ASPInsider, MCSD, Certified ScrumMaster, Microsoft MVP in ASP.NET, and author
of Beginning ASP.NET 2.0 AJAX by Wrox. He s
been developing software solutions for leading companies in the Seattle area
for more than a decade. When he s not busy designing software systems or
writing about them, he often can be found loitering at local user groups and
habitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.net or e-mail him at mailto:[email protected].Control Attributes
[ToolboxData("<{0}:AttCtrl runat=server>{0}:AttCtrl>")]
public class AttCtrl : WebControl
{
//TODO: implement control internals...
}
Property Attributes
Figure 5: The value supplied by the
Description attribute gets displayed at the bottom of the Properties window. Soothe Growing Pains
Advanced Tips & Tricks
Figure 9: A single line of code is
all it takes to invoke this common dialog box. Conclusion
Custom Control Attributes
(March 2009 Issue)
0 comments
Hide comments