WEBSITE

The AJAX Control Toolkit : Enhancing Controls with Extenders

10/10/2010 11:27:12 AM
ASP.NET comes with a fairly rich collection of built-in controls. In addition, plenty of custom controls are available for developers from third-party vendors, from community projects, and even from contributions by volunteers. If you still can’t find the control you are looking for, you typically write one yourself or buy a new specialized control that extends the original control and adds the desired behavior. Object orientation, of course, encourages this approach.

All in all, it’s rare that you need to write a completely new control yourself. More often, your control will derive from an existing ASP.NET control. Blindly using inheritance for building specialized versions of controls might not be a wise choice, though. Even in relatively small projects, in fact, it can lead straight to a proliferation of controls.

ASP.NET control extenders go in the opposite direction. First and foremost, an extender control is a server control itself. An extender represents a logical behavior that can be attached to one or more control types to extend their base capabilities. Extenders decouple controls from behaviors and make it possible to extend existing controls with new behaviors.

From a technology point of view, ASP.NET AJAX and extenders are not strictly related. In theory, one could develop extenders for ASP.NET 1.1 and ASP.NET 2.0 that work without AJAX extensions. In practice, though, ACT provides some interesting facilities for writers of extender controls—specifically, base classes and, more importantly, the Microsoft AJAX library for developing JavaScript functionalities more comfortably.

Extenders at a Glance: the TextBoxWatermark Control

To better understand the goals and characteristics of control extenders, let’s briefly consider the behavior encapsulated by one of the extenders contained in the ACT—the TextBoxWatermark extender.

A text box watermark is a string of text that is displayed in an empty text box as a guide to the user. This help text is stripped off when the text box is submitted and is automatically removed as the user starts typing in the field. Likewise, it is automatically re-inserted when the user wipes out any text in the text box. You start by linking the ACT assembly to the project and then place an extendee TextBox control in the page:

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="act" %>
...
<asp:TextBox ID="TextBox1" runat="server" />



Later in the ASPX source, you add a new control—the TextBoxWatermarkExtender control:

<act:TextBoxWatermarkExtender runat="server" ID="TextBoxWatermark1"
TargetControlID="TextBox1"
WatermarkText="Type First Name Here"
WatermarkCssClass="watermarked" />

The watermark extender targets the specified control ID and adds a new behavior to it. The behavior is further configured using a few public properties on the extender control, such as WatermarkText and WatermarkCssClass in the previous example.

In particular, the watermark behavior injects script code that hooks up three HTML events: onfocus, onblur, and onkeypress. In its initialization stage, the injected script also sets a new style and default text for the target text box if the body of the field is empty. When the text box gets the input focus, the event handler promptly removes the watermark text and restores the original style. As the user types, the handler for onkeypress ensures that the current text box is watermarked. Finally, when the input field loses the focus—the onblur event—the handler sets the watermark back if the content of the field is the empty string.

Note

To add a watermark behavior to an ASP.NET TextBox, you use the aforementioned extender control. Alternatively, if you feel comfortable with ASP.NET control development and JavaScript, you can develop a custom TextBox control and use a client-side code fragment to achieve the same results.


Creating a New Extender Control

ASP.NET 3.5 doesn’t include any concrete implementation of an extender. However, it defines the base class from which all custom extenders, as well as all extenders in the ACT, derive. This class is named ExtenderControl. You can create your own extenders starting from this class; it is not recommended, though. Why is it so? There’s an easier and faster way that leverages the extensions available in the ACT library.

The following code shows the source code of the focus extender control. The sample extender adds to its target control a highlighting behavior that changes the appearance of the control when this gets focused:

using AjaxControlToolkit;
...
namespace Core35
{
[TargetControlType(typeof(Control))]
[ClientScriptResource("Core35.FocusBehavior", "focusBehavior.js")]
public class FocusExtender : AjaxControlToolkit.ExtenderControlBase
{
[ExtenderControlProperty]
[RequiredProperty]
public string HighlightCssClass
{
get { return GetPropertyValue("HighlightCssClass", ""); }
set { SetPropertyValue("HighlightCssClass", value); }
}

[ExtenderControlProperty]
public string NoHighlightCssClass
{
get { return GetPropertyValue("NoHighlightCssClass", ""); }
set { SetPropertyValue("NoHighlightCssClass", value); }
}
}
}



The TargetControlType attribute indicates the type of controls this behavior can be attached to. The ClientScriptResource attribute indicates the name of the script class to inject in the client page and its source file. The base class is ExtenderControlBase, which is defined in the ACT library.

All that you do with managed code is define the set of properties that developers can customize on the both the server and the client. Each property must be decorated with the ExtenderControlProperty attribute and, optionally, the RequiredProperty attribute.

The property is not directly responsible for the persistence of its assigned value. It is limited to getting and setting the value through the GetPropertyValue and SetPropertyValue methods of the base class. These stock methods take care of persistence.

The core part of an AJAX extender control is its JavaScript code. Here’s the JavaScript code you need for the focus extender:

Type.registerNamespace('Core35');

Core35.FocusBehavior = function(element)
{
Core35.FocusBehavior.initializeBase(this, [element]);

this._highlightCssClass = null;
this._nohighlightCssClass = null;
}

Core35.FocusBehavior.prototype =
{
initialize : function() {
Core35.FocusBehavior.callBaseMethod(this, 'initialize');
this._onfocusHandler = Function.createDelegate(this, this._onFocus);
this._onblurHandler = Function.createDelegate(this, this._onBlur);
$addHandlers(this.get_element(),
{ 'focus' : this._onFocus,
'blur' : this._onBlur },
this);
this.get_element().className = this._nohighlightCssClass;
},
dispose : function() {
$clearHandlers(this.get_element());
Core35.FocusBehavior.callBaseMethod(this, 'dispose');
},
_onFocus : function(e) {
if (this.get_element() && !this.get_element().disabled) {
this.get_element().className = this._highlightCssClass;
}
},
_onBlur : function(e) {
if (this.get_element() && !this.get_element().disabled) {
this.get_element().className = this._nohighlightCssClass;
}
},
get_highlightCssClass : function() {
return this._highlightCssClass;
},
set_highlightCssClass : function(value) {
if (this._highlightCssClass !== value) {
this._highlightCssClass = value;
this.raisePropertyChanged('highlightCssClass');
}
},
get_nohighlightCssClass : function() {
return this._nohighlightCssClass;
},
set_nohighlightCssClass : function(value) {
if (this._nohighlightCssClass !== value) {
this._nohighlightCssClass = value;
this.raisePropertyChanged('nohighlightCssClass');
}
}
}

// Optional descriptor for JSON serialization
Core35.FocusBehavior.descriptor = {
properties: [ {name: 'highlightCssClass', type: String},
{name: 'nohighlightCssClass', type: String} ]
}

// Register the class as a type that inherits from Sys.UI.Control.
Core35.FocusBehavior.registerClass('Core35.FocusBehavior', Sys.UI.Behavior);



The script for the extender is centered around a couple of handlers for focus and blur DOM events. In the focus handler, the code sets the CSS class for the target element. In the blur handler, it resets the CSS class.

Tip

The easiest way to create extenders is to use the facilities of the ACT. You run the VSI file in the toolkit download, set up the templates, and then click “Add AJAX Control Extender” from the Visual Studio 2008 Solution Explorer to obtain a scaffold for the extender and the behavior.


In a test page, all that you have to do is register the ACT assembly and the assembly that contains the focus extender and then go with the following code:

<asp:TextBox ID="TextBox1" runat="server" EnableTheming="false" />
<act:FocusExtender ID="FocusExtender1" runat="server"
TargetControlID="TextBox1"
NoHighlightCssClass="LowLightTextBox"
HighlightCssClass="HighLight" />

You can attach the focus extender behavior to virtually all ASP.NET controls and, for each control, you can specify the CSS class to use to render the control as highlighted and normal. Bear in mind that you need to disable theming to make sure that CSS styles you apply through the extender take precedence over any other style set via themes. Figure 1 shows the extender in action.

Figure 1. The focus behavior in action


Extenders in the ACT

Table 1 lists the components available in the ACT. Note that the full name of the extender class contains an “Extender” suffix that I omitted in the table for brevity. So, for example, there will be no CollapsiblePanel component in the ACT assembly; you will find a CollapsiblePanelExtender control instead.

Table 1. Extenders in the ACT
ControlDescription
AlwaysVisibleControlPins a control to a corner of the page, and keeps it floating over the page background as the user scrolls or resizes the page. You use this extender to make sure that, say, a given panel shows up at the top-left corner of the page regardless of the scroll position or the size of the browser window.
AnimationProvides a specialized framework for adding animation effects to controls hosted in ASP.NET pages. You associate client-side events of the target control with one or more of the predefined animation effects.
AutoCompleteAssociated with a text box, provides a list of suggestions for the text to type in the field.
CalendarAttached to a text box, the extender provides client-side date-picking functionality with customizable date format and pop-up control.
CascadingDropDownAssociated with a DropDownList control. This extender automatically populates the list with data retrieved from a Web service method. The nice thing about this extender is that you can create a hierarchy of drop-down lists and have the extender automatically populate child drop-down lists based on the current selections in any of the previous lists in the hierarchy, if any.
CollapsiblePanelAdds collapsible sections to a Web page. This extender can be used only with panel controls—that is, with the ASP.NET Panel control or any class derived from it. You let the extender know which panel in the page acts as the header and which panel provides the contents that collapse and expand.
ConfirmButtonAssociated with a button control. This extender adds a confirmation JavaScript dialog box to the click event of the button. The extender is supported on any class that implements the IButtonControl interface, including Button, LinkButton, and ImageButton.
DragPanelAssociated with panel controls. This extender adds drag-and-drop capabilities so that you can move the panel around the page. You can specify the contents to move as well as the handle that, if pressed, triggers the dragging operation.
DropDownThe extender provides a mouse-over link to open a drop-down panel.
DropShadowAdds drop shadows to any control available on the page. With this extender, you can specify the opacity and width of the shadow.
DynamicPopulateUpdates the contents of a control with the result of a Web service or page method call.
FilteredTextBoxLets users enter text in a TextBox control that matches a given set of valid characters.
HoverMenuDisplays the contents of an associated panel control when the mouse hovers next to a given control. You can associate this extender with any ASP.NET control. The extender works as a kind of specialized and extremely flexible ToolTip.
ListSearchEnables users to search for an item in a list by typing some of the characters.
MaskedEditLets users enter text in a TextBox control according to a given input layout.
ModalPopupAssociated with a control that can fire a client-side onclick event (typically, buttons and hyperlinks), this extender implements a classic modal dialog box without using HTML dialog boxes. Basically, it displays the contents of a given panel and prevents the user from interacting with the rest of the page.
MutuallyExclusiveCheckBoxAssociated with CheckBox controls, this extender lets you define logical groups of check boxes so that users can select only one in each group.
NoBotApplies some anti-bot techniques to input forms. Bots, or robot applications, are software applications that run automated tasks over the Internet. For example, bots are used to fill input forms and submit ad hoc values.
NumericUpDownAssociated with text box controls, this extender allows you to click automatically displayed buttons to enter the next/previous value in the field. It works with numbers, custom lists, and Web service methods.
PagingBulletedListAssociated with BulletedList controls, this extender groups all items bound to the list and organizes them in client-side sorted pages.
PasswordStrengthAssociated with text box controls used to type a password, this extender provides visual feedback on the strength of the password being typed.
PopupControlTransforms the contents of a given panel into a pop-up window without using HTML dialog boxes. You can associate this extender with any control that can fire any of the following client-side events: onfocus, onclick, and onkeydown.
ResizableControlAttaches to any page element, and allows the user to resize the element using a handle placed at the lower-right corner of the control.
RoundedCornersAdds a background panel to any ASP.NET control so that the control appears with rounded corners. The overall height of the original control changes slightly.
SliderExtends a TextBox control with a slider user interface.
SlideShowAssociated with Image controls, it can be used to transition images automatically when hosted on a page.
TextBoxWatermarkAssociated with TextBox controls. This extender adds sample or prompt text, called a “watermark,” that illustrates the type of text the user is expected to enter in the field. For example, the watermark might say, “Type your name here.” The watermark text disappears as soon as the user starts typing and reappears if the text box becomes empty.
ToggleButtonAssociated with CheckBox controls. This extender enables you to use custom images to render the check buttons. You can use different images to indicate the selected and cleared states.
UpdatePanelAnimationPlays animations during key steps of a partial update. You can use the extender to animate the page both while the panel is being updated and when the update has completed.
ValidatorCalloutWorks on top of ASP.NET validators, and improves their user interface. In particular, the extender displays a yellow callout with the error message.

As you can probably guess, some extenders listed in the table require rich browser capabilities, whereas others are just a smart piece of JavaScript code attached to a block of markup elements. Note that all these features work in a cross-browser way. I’ll return to some of the aforementioned extenders with code samples and more details in a moment. For more complete documentation, please refer to http://www.asp.net/ajax/ajaxcontroltoolkit/samples.

Other  
 
Most View
Looking Good, Sounding Great (Part 1) : Q Acoustics Q7000i 5.1, Bowers & Wilkins MT-50, Canton Movie 1050
Tech Of The Year 2013 (Part 3) - Corsair RM750, Intel 4th Gen Core I7-4770K, ASUS GTX780TI-3GD5
The Contemporary APUs - AMD Trinity vs Intel Ivy Bridge (Part 4)
Nikon D7100 DSLR – A Camera Providing Excellent Images (Part 2)
Lenovo Ideatab S2110 - A Transformer’s Strong Competitor Running Android 4.0 (Part 2)
Boston Value Series 115T - The Highest Scalability and the Lowest Possible Power
Open GL : Storing Transformed Vertices—Transform Feedback (part 3)
Acer Aspire R7 - A Flexible Form Factor With A Reasonable Price (Part 2)
GIGABYTE GeForce GTX 660 Ti OC Version
Delete & Recover Data (Part 1)
Top 10
Sharepoint 2013 : Farm Management - Disable a Timer Job,Start a Timer Job, Set the Schedule for a Timer Job
Sharepoint 2013 : Farm Management - Display Available Timer Jobs on the Farm, Get a Specific Timer Job, Enable a Timer Job
Sharepoint 2013 : Farm Management - Review Workflow Configuration Settings,Modify Workflow Configuration Settings
Sharepoint 2013 : Farm Management - Review SharePoint Designer Settings, Configure SharePoint Designer Settings
Sharepoint 2013 : Farm Management - Remove a Managed Path, Merge Log Files, End the Current Log File
SQL Server 2012 : Policy Based Management - Evaluating Policies
SQL Server 2012 : Defining Policies (part 3) - Creating Policies
SQL Server 2012 : Defining Policies (part 2) - Conditions
SQL Server 2012 : Defining Policies (part 1) - Management Facets
Microsoft Exchange Server 2010 : Configuring Anti-Spam and Message Filtering Options (part 4) - Preventing Internal Servers from Being Filtered