Creating a Custom AJAX Control Toolkit Control Extender (C#)
In this tutorial, you learn how to
create a custom AJAX Control Toolkit control extender. We create a simple,
but useful, new extender that changes the state of a Button from disabled
to enabled when you type text into a TextBox. After reading this tutorial,
you will be able to extend the ASP.NET AJAX Toolkit with your own control
extenders.
You can create custom control extenders
using either Visual Studio or Visual Web Developer (make sure that you
have the latest version of Visual Web Developer).
Overview of the
DisabledButton Extender
Our new control extender is named the
DisabledButton extender. This extender will have three properties:
- TargetControlID - The
TextBox that the control extends.
- TargetButtonIID - The
Button that is disabled or enabled.
- DisabledText - The text
that is initially displayed in the Button. When you start typing, the
Button displays the value of the Button Text property.
You hook the DisabledButton extender
to a TextBox and Button control. Before you type any text, the Button
is disabled and the TextBox and Button look like this:
After you start typing text, the Button
is enabled and the TextBox and Button look like this:
To create our control extender, we
need to create the following three files:
- DisabledButtonExtender.cs
- This file is the server-side control class that will manage creating
your extender and allow you to set the properties at design-time. It
also defines the properties that can be set on your extender. These
properties are accessible via code and at design time and match properties
defined in the DisableButtonBehavior.js file.
- DisabledButtonBehavior.js
-- This file is where you will add all of your client script logic.
- DisabledButtonDesigner.cs
- This class enables design-time functionality. You need this class
if you want the control extender to work correctly with the Visual Studio/Visual
Web Developer Designer.
So a control extender consists of a
server-side control, a client-side behavior, and a server-side designer
class. You learn how to create all three of these files in the following
sections.
Creating the Custom
Extender Website and Project
The first step is to create a class
library project and website in Visual Studio/Visual Web Developer. We�ll
create the custom extender in the class library project and test the
custom extender in the website.
Let�s start with the website. Follow
these steps to create the website:
- Select the menu option
File, New Web Site.
- Select the ASP.NET Web
Site template.
- Name the new website
Website1.
- Click the OK button.
Next, we need to create the class library
project that will contain the code for the control extender:
- Select the menu option
File, Add, New Project.
- Select the Class Library
template.
- Name the new class library
with the name CustomExtenders.
- Click the OK button.
After you complete these steps, your
Solution Explorer window should look like Figure 1.
Next, you need to add all of the necessary
assembly references to the class library project:
- Right-click the CustomExtenders
project and select the menu option Add Reference.
- Select the .NET tab.
- Add references to the following
assemblies:
- System.Web.dll
- System.Web.Extensions.dll
- System.Design.dll
- System.Web.Extensions.Design.dll
- Select the Browse tab.
- Add a reference to the AjaxControlToolkit.dll
assembly. This assembly is located in the folder where you downloaded
the AJAX Control Toolkit.
After you complete these steps, your
class library project References folder should look like Figure 2.
Creating the Custom
Control Extender
Now that we have our class library,
we can start building our extender control. Let�s start with the bare
bones of a custom extender control class (see Listing 1).
Listing 1
- MyCustomExtender.cs
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
[assembly: System.Web.UI.WebResource("CustomExtenders.MyControlBehavior.js", "text/javascript")]
namespace CustomExtenders
{
[ClientScriptResource("CustomExtenders.MyControlBehavior", "CustomExtenders.MyControlBehavior.js")]
[TargetControlType(typeof(TextBox))]
public class MyControlExtender : ExtenderControlBase
{
[ExtenderControlProperty]
[DefaultValue("")]
public string MyProperty
{
get
{
return GetPropertyValue("MyProperty", "");
}
set
{
SetPropertyValue("MyProperty", value);
}
}
}
}
There are several things that you notice
about the control extender class in Listing 1. First, notice that the
class inherits from the base ExtenderControlBase class. All AJAX Control
Toolkit extender controls derive from this base class. For example,
the base class includes the TargetID property that is a required property
of every control extender.
Next, notice that the class includes
the following two attributes related to client script:
- WebResource - Causes a
file to be included as an embedded resource in an assembly.
- ClientScriptResource -
Causes a script resource to be retrieved from an assembly.
The WebResource attribute is used to
embed the MyControlBehavior.js JavaScript file into the assembly when
the custom extender is compiled. The ClientScriptResource attribute
is used to retrieve the MyControlBehavior.js script from the assembly
when the custom extender is used in a web page.
In order for the WebResource and ClientScriptResource
attributes to work, you must compile the JavaScript file as an embedded
resource. Select the file in the Solution Explorer window, open the
property sheet, and assign the value Embedded Resource to the
Build Action property.
Notice that the control extender also
includes a TargetControlType attribute. This attribute is used to specify
the type of control that is extended by the control extender. In the
case of Listing 1, the control extender is used to extend a TextBox.
Finally, notice that the custom extender
includes a property named MyProperty. The property is marked with the
ExtenderControlProperty attribute. The GetPropertyValue() and SetPropertyValue()
methods are used to pass the property value from the server-side control
extender to the client-side behavior.
Let�s go ahead and implement the
code for our DisabledButton extender. The code for this extender can
be found in Listing 2.
Listing 2
- DisabledButtonExtender.cs
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
[assembly: System.Web.UI.WebResource("CustomExtenders.DisabledButtonBehavior.js", "text/javascript")]
namespace CustomExtenders
{
[ClientScriptResource("CustomExtenders.DisabledButtonBehavior", "CustomExtenders.DisabledButtonBehavior.js")]
[TargetControlType(typeof(TextBox))]
public class DisabledButtonExtender : ExtenderControlBase
{
[ExtenderControlProperty]
[DefaultValue("")]
[IDReferenceProperty(typeof(Button))]
public string TargetButtonID
{
get
{
return GetPropertyValue("TargetButtonID", "");
}
set
{
SetPropertyValue("TargetButtonID", value);
}
}
[ExtenderControlProperty]
[DefaultValue("")]
public string DisabledText
{
get
{
return GetPropertyValue("DisabledText", "");
}
set
{
SetPropertyValue("DisabledText", value);
}
}
}
}
The DisabledButton extender in Listing
2 has two properties named TargetButtonID and DisabledText. The
IDReferenceProperty applied to the TargetButtonID property prevents
you from assigning anything other than the ID of a Button control to
this property.
The WebResource and ClientScriptResource
attributes associate a client-side behavior located in a file named
DisabledButtonBehavior.js with this extender. We discuss this JavaScript
file in the next section.
Creating the Custom
Extender Behavior
The client-side component of a control
extender is called a behavior. The actual logic for disabling and enabling
the Button is contained in the DisabledButton behavior. The JavaScript
code for the behavior is included in Listing 3.
Listing 3
- DisabledButton.js
Type.registerNamespace('CustomExtenders');
CustomExtenders.DisabledButtonBehavior = function(element) {
CustomExtenders.DisabledButtonBehavior.initializeBase(this, [element]);
this._targetButtonIDValue = null;
this._disabledTextValue = null;
}
CustomExtenders.DisabledButtonBehavior.prototype = {
initialize : function() {
CustomExtenders.DisabledButtonBehavior.callBaseMethod(this, 'initialize');
// Initalization code
$addHandler(this.get_element(), 'keyup',
Function.createDelegate(this, this._onkeyup));
this._onkeyup();
},
dispose : function() {
// Cleanup code
CustomExtenders.DisabledButtonBehavior.callBaseMethod(this, 'dispose');
},
// Property accessors
//
get_TargetButtonID : function() {
return this._targetButtonIDValue;
},
set_TargetButtonID : function(value) {
this._targetButtonIDValue = value;
},
get_DisabledText : function() {
return this._disabledTextValue;
},
set_DisabledText : function(value) {
this._disabledTextValue = value;
},
_onkeyup : function() {
var e = $get(this._targetButtonIDValue);
if (e) {
var disabled = ("" == this.get_element().value);
e.disabled = disabled;
if ( this._disabledTextValue) {
if (disabled) {
this._oldValue = e.value;
e.value = this._disabledTextValue;
}
else
{
if(this._oldValue){
e.value = this._oldValue;
}
}
}
}
}
}
CustomExtenders.DisabledButtonBehavior.registerClass('CustomExtenders.DisabledButtonBehavior', AjaxControlToolkit.BehaviorBase);
The JavaScript file in Listing 3 contains
a client-side class named DisabledButtonBehavior. This class, like its
server-side twin, includes two properties named TargetButtonID and DisabledText
which you can access using get_TargetButtonID/set_TargetButtonID
and get_DisabledText/set_DisabledText.
The initialize() method associates
a keyup event handler with the target element for the behavior. Each
time you type a letter into the TextBox associated with this behavior,
the keyup handler executes. The keyup handler either enables or disables
the Button depending on whether the TextBox associated with the behavior
contains any text.
Remember that you must compile the
JavaScript file in Listing 3 as an embedded resource. Select the file
in the Solution Explorer window, open the property sheet, and assign
the value Embedded Resource to the Build Action property
(see Figure 3). This option is available in both Visual Studio and Visual
Web Developer.
Creating the Custom
Extender Designer
There is one last class that we need
to create to complete our extender. We need to create the designer class
in Listing 4. This class is required to make the extender behave correctly
with the Visual Studio/Visual Web Developer Designer.
Listing 4
- DisabledButtonDesigner.cs
using System.Web.UI.WebControls;
using System.Web.UI;
namespace CustomExtenders
{
class DisabledButtonDesigner : AjaxControlToolkit.Design.ExtenderControlBaseDesigner
{
}
}
You associate the designer in Listing
4 with the DisabledButton extender with the Designer attribute.You need
to apply the Designer attribute to the DisabledButtonExtender class
like this:
[Designer(typeof(DisabledButtonDesigner))]
[ClientScriptResource("CustomExtenders.DisabledButtonBehavior", "CustomExtenders.DisabledButtonBehavior.js")]
[TargetControlType(typeof(TextBox))]
public class DisabledButtonExtender : ExtenderControlBase
{
Using the Custom
Extender
Now that we have finished creating
the DisabledButton control extender, it is time to use it in our ASP.NET
website. First, we need to add the custom extender to the toolbox. Follow
these steps:
- Open an ASP.NET page by
double-clicking the page in the Solution Explorer window.
- Right-click the toolbox
and select the menu option Choose Items.
- In the Choose Toolbox Items
dialog, browse to the CustomExtenders.dll assembly.
- Click the OK button
to close the dialog.
After you complete these steps, the
DisabledButton control extender should appear in the toolbox (see Figure
4).
Next, we need to create a new ASP.NET
page. Follow these steps:
- Create a new ASP.NET page
named ShowDisabledButton.aspx.
- Drag a ScriptManager onto
the page.
- Drag a TextBox control onto
the page.
- Drag a Button control onto
the page.
- In the Properties window,
change the Button ID property to the value btnSave and the Text
property to the value Save*.
We created a page with a standard ASP.NET
TextBox and Button control.
Next, we need to extend the TextBox
control with the DisabledButton extender:
- Select the Add Extender
task option to open the Extender Wizard dialog (see Figure 5). Notice
that the dialog includes our custom DisabledButton extender.
- Select the DisabledButton
extender and click the OK button.
Finally, we can set the properties
of the DisabledButton extender. You can modify the properties of the
DisabledButton extender by modifying the properties of the TextBox control:
- Select the TextBox in the
Designer.
- In the Properties window,
expand the Extenders node (see Figure 6).
- Assign the value Save
to the DisabledText property and the value btnSave to the TargetButtonID
property.
When you run the page (by hitting F5),
the Button control is initially disabled. As soon as you start entering
text into the TextBox, the Button control is enabled (see Figure 7).
Summary
The goal of this tutorial was to explain
how you can extend the AJAX Control Toolkit with custom extender controls.
In this tutorial, we created a simple DisabledButton control extender.
We implemented this extender by creating a DisabledButtonExtender class,
a DisabledButtonBehavior JavaScript behavior, and a DisabledButtonDesigner
class. You follow a similar set of steps whenever you create a custom
control extender.