Other neat stuff
The following items represent some handy tips, techniques, and features that are available with the AJAX Control Toolkit.
A brief description is provided here along with a reference to one or more samples that demonstrate the use of the concept in complete detail.
Using data binding to specify Extender properties
If you want to initialize Extender instances dynamically from data (instead of with server-side code), this is now supported.
The example below demonstrates setting the "WatermarkText" property of a TextBoxWatermark from the "WatermarkTextField" value of a data source.
An working example of Extender data binding within a Repeater can be found in the DataBinding.aspx automated test (in the ToolkitTests folder).
<ajaxToolkit:TextBoxWatermarkExtender ID="TBWE" runat="server"
TargetControlID="TextBox1"
WatermarkText='<%# Eval("WatermarkTextField") %>' />
Maintaining state on the client
Sometimes it's handy to maintain state on the client side across postbacks to the server.
This is made easy by the ClientState property implemented by ExtenderControlBase and Behavior.js.
Look at the script for AlwaysVisibleControl, CascadingDropDown, CollabsiblePanel, PopupControl, RoundedCorners, or TextboxWatermark for examples.
Making sure required properties have values
Missing properties for required fields should be easy to identify - and they are if you use the RequiredPropertyAttribute or the ExtenderControlBase.EnsureValid override.
In most cases, you can simply add the RequiredPropertyAttribute to any required properties and an exception will automatically be thrown if they're not set.
See the Properties classes for CascadingDropDown, HoverMenu, ModalPopup, PopupControl, TextboxWatermark, or ToggleButton for examples.
If the checking of required fields is a little more involved, simply override the EnsureValid method and add whatever logic you need.
Look at the Properties classes for AlwaysVisibleControl or CollapsiblePanel for examples.
Easily modifying and debugging scripts
Scripts are automatically referenced as embedded resources by default which is very handy for using and deploying them.
However, it can make developing and debugging them a little harder.
When developing scripts, simply return true from AllowScriptPath (done by default) and set the ScriptPath of your extender to point to a script file somewhere in your website project.
The script will be automatically referenced from the web site, so it will be easier to change and debug.
When you're ready to deploy it, simply remove the ScriptPath and the script will be accessed from the resource again.
For example:
<name:MyExtender ID="MyExtender1" ScriptPath="MyBehavior.js"
runat="server">
Sharing common code
If you have some handy script functions that you'd like to make available to multiple controls, you can put that code in the Common.js file and add the RequiredScriptAttribute to your class and reference the CommonToolkitScripts type.
The common script will automatically be available to your control at run time!
See the CascadingDropDown or HoverMenu for examples.
Easily referencing behavior instances
It used to be tricky to get a reference to a behavior from client script, but now you can simply add a "BehaviorID" attribute to your control's property specification and it will be easily accessible on the client via ASP.NET AJAX's Sys.Application.findComponent(id) method or its $find(id) shortcut.
(Note: If BehaviorID isn't specified, the behavior's ID on the client will be the same as the extender control's ClientID.)
See DynamicPopulate or ResizableControl for examples.
Finding controls in unusual locations
The ExtenderControlBase class tries to find controls used by extenders, but if those controls are buried within other naming containers, it may not be able to find them.
When that happens, it will fire the ResolveControlID event and any event handlers registered by the page author will be able to identify the relevant control by using the additional context available to the page developer.
See the ExtenderBase test page for an example.
Easily adding dynamic population
The DynamicPopulate*Base classes (DynamicPopulateExtenderControlBase and DynamicPopulateBehaviorBase) make adding dynamic population to a new or existing extender simple.
Just derive the extender's code from the DynamicPopulate*Base classes to get the necessary properties (DynamicControlID, DynamicContextKey, DynamicServicePath, and DynamicServiceMethod) for users to (optionally) hook up the population feature.
When your behavior implementation makes a base method call to the "populate" function, the relevant page content will be dynamically updated by the DynamicPopulate control.
Population can be done with a page method or a web service and works just as it does when using DynamicPopulate directly.
Look at HoverMenu, ModalPopup, or PopupControl for examples.
Automatically expanding virtual paths
If your control has a property that accepts a path from the user, mark that property with the UrlPropertyAttribute and virtual paths will be automatically resolved.
See CascadingDropDown, CollapsiblePanel, or ToggleButton for examples.
Hooking up to partial update (UpdatePanel) events
All controls with a behavior deriving from BehaviorBase have _partialUpdateBeginRequest and _partialUpdateEndRequest methods and a registerPartialUpdateEvents method to enable them.
By calling the registerPartialUpdateEvents method, the PageRequestManager's begin/end request events are automatically used to call the _partialUpdateBeginRequest and _partialUpdateEndRequest methods.
_partialUpdateBeginRequest is called when a partial rendering (i.e., an UpdatePanel postback) begins and _partialUpdateEndRequest is called when it ends.
Look at the PopupControl, TextBoxWatermark, or UpdatePanelAnimation behaviors for examples.
Wrapping an existing behavior
If you want your extender to take advantage of or expose one of the many existing ASP.NET AJAX behaviors, it's easy to do.
Look at the AlwaysVisibleControl, DropShadow, HoverMenu, ModalPopup, PopupControl, or ReorderList for examples.
Exposing properties to the designer with customized names
If you want to expose a property to the designer or script code with a different name than the property itself, just decorate that property with the ClientPropertyNameAttribute.
(Note that this is a common scenario when wrapping existing behaviors.)
Look at the DragPanel's DragHandleID property for an example.
Adding required script references
If you want to add some required script references to the page to support your behavior, you can do so with the RequiredScriptAttribute.
RequiredScriptAttribute supports referencing required scripts with the FrameworkScript enum or by referring to another extender type that you want to use.
It also allows you to specify a specific load order for those cases where the default behavior needs to be altered.
Look at the AlwaysVisibleControl, CascadingDropDown, CollapsiblePanel, DragPanel, DropShadow, HoverMenu, ModalPopup, or ReorderList for examples.