In the earlier article "Explorer Ways to extend ASP.NET
AJAX Client-side Function," we demonstrated how to enrich an HTML
<div> element by setting different CSS styles when the mouse hovers/unhovers
over it with the help of a client behavior. Now that we have implemented this
client component, it is pretty suitable to build an extender to wire it to ASP.NET
server controls in different web applications. And since we have the code for
the MyHoverBehavior class stored in a JavaScript file we
have completed the first phase of the whole process and can move to the second
phase.
Create an ASP.NET AJAX-enabled Web Site
Launch Visual Studio 2005 and select template "ASP.NET
AJAX-enabled Web Site" to create a web site named ServHoverBehavior,
as well as select Visual C# as the built-in language. Next, right click the
project and select "New folder" to create a folder named ScriptLibrary. Then we can, for brevity, copy the JScript
file MyHoverBehavior.js (although it was created in
Sample 1 in the above-mentioned earlier article we should have to make a little modification with it later) to this folder.
Also, we can copy file intro.css to the root folder of this
website. And also, for easier debugging the JScript file MyHoverBehavior.js,
we had better add a reference to assembly System.Web.Extensions.dll,
which will result in a Bin folder in the website.
Now, we are ready to move to the next phase to create a server-side
extender class and implement the server-side logic.
Create the Server-side Extender Class
1. Mapping client properties to the server ones
Now that the client functionality has been encapsulated in a
client component, we need to filter the client properties that we want to
configure on the server side so that we can create corresponding properties in
the extender class and use them to set the value of the client properties. All
that makes this possible is use a script descriptor.
To set their values from the server side, we need to expose
corresponding properties in the extender. For more clarity, we can draw a table
to illustrate the relationship between the properties of the two components we
are to create in JavaScript.
Table 2—mappings between client properties and
extender ones
Client property
|
Extender property
|
unhoverDelay
|
UnhoverDelay
|
hoverScript
|
HoverScript
|
unhoverScript
|
UnhoverScript
|
2. Creating the extender
As mentioned above, an extender is a class that inherits
from the base System.Web.UI.ExtenderControl. Therefore, we can simply
right-click the project and add a class named ServHoverBehavior,
which will result in generating an App_Code sub folder
automatically by the system.
Next, we should let the class derive from ExtenderControl,
adding the necessary server-side properties and overriding the related methods
defined in the IExtenderControl interface. Here, we
directly listed the related source code.
Listing 4
namespace ZXZSamples.CS
{
[TargetControlType(typeof(Control))]
public class ServHoverBehavior: ExtenderControl
{
public int UnhoverDelay
{
get
{
return (int)ViewState["UnhoverDelay"];
}
set
{
ViewState["UnhoverDelay"] = value;
}
}
public string HoverScript
{
get
{
return (string)ViewState["HoverScript"];
}
set
{
ViewState["HoverScript"] = value;
}
}
public string UnhoverScript
{
get
{
return (string)ViewState["UnhoverScript"];
}
set
{
ViewState["UnhoverScript"] = value;
}
}
public string ScriptPath
{
get
{
return (string)ViewState["ScriptPath"];
}
set
{
ViewState["ScriptPath"] = value;
}
}
protected override IEnumerable < ScriptDescriptor > GetScriptDescriptors
(Control targetControl)
{
ScriptBehaviorDescriptor desc = new ScriptBehaviorDescriptor(
"ZXZSamples.MyHoverBehavior", targetControl.ClientID);
desc.AddProperty("unhoverDelay", this.UnhoverDelay);
desc.AddProperty("hoverScript", this.HoverScript);
desc.AddProperty("unhoverScript", this.UnhoverScript);
yield return desc;
}
protected override IEnumerable < ScriptReference > GetScriptReferences()
{
yield return new ScriptReference(Page.ResolveClientUrl(this.ScriptPath));
}
}
}
First, by putting above the class declaration a TargetControlType attribute we put a constraint on the types
of server controls that the extender can extend (since we specify the type is Control we can wire the behavior to nearly any ASP.NET server
controls).
Next, we expose a ScriptPath
property which is used to specify the location of the JavaScript file that contains
the code of the MyHoverBehavior behavior. The property
is not listed in the above table because it is not exposed by the client
component. However, we will need it when creating the ScriptReference
instance. All the other properties store the values assigned to the corresponding
properties of the client behavior. Note, here we store and retrieve all the
values from the ViewState of the extender control.
As for the last two overridden methods, method GetScriptDescriptors takes care of returning a script
descriptor for the MyHoverBehavior behavior. In the override,
the script descriptor uses the values of the server UnhoverDelay,
HoverScript, and UnhoverScript
properties to build a $create statement that contains
values for the client related properties, while method GetScriptReferences
returns a ScriptReference instance with the information needed to load the
right JavaScript file in the page.
Author's Note: In the above JScript
file, MyHoverBehavior.js, we introduced two new properties hoverScript and unhoverScript.
Therefore, here appear their corresponding server-side properties. These two
properties hold two pieces of the related JavaScript code snippet that
corresponds respectively to the hover and unhover events of the behavior. When the events fire, with
the help of function eval of JavaScript, we execute the
JavaScript code snippet held inside the above two properties—hoverScript
and unhoverScript. You can find the similar
implementation in the source code of entender HoverExtender
shipped with AjaxControlToolkit.
Using the ServHoverBehavior extender
In fact, an extender is nothing more than a custom ASP.NET
server control. Therefore, we can follow the same rules as any other server
control to register and declare an extender in an ASP.NET page.
To use the above extender in an ASP.NET page, all we have to
do is register the namespace that contains the ServHoverBehavior
class in the page that will use it:
<%@ Register Namespace="ZXZSamples.CS" TagPrefix="samples" %>
Now, it is time to wire the extender to its target control. Listing
5 shows an ASP.NET Panel control with an associated ServHoverBehavior
control in our sample.
Listing 5 - Extending an ASP.NET web control
declaratively
<div>
<asp:Panel ID="panel1" runat="server" Height="37px" Width="354px"
BorderWidth="1px">
Move the mouse over ME and watch!
</asp:Panel>
</div>
<samples:ServHoverBehavior ID="MyHoverBehaviorExtender1" runat="server"
TargetControlID="panel1"
ScriptPath="~/ScriptLibrary/MyHoverBehavior.js"
UnhoverDelay=30 HoverScript="SetHoverCSS();" UnhoverScript="SetUnhoverCSS();">
</samples:ServHoverBehavior>
All the magic of extenders happens when we set the extender
control’s Target-ControlID property to the ID of the target control. Here, we
extend the Panel by assigning its ID to the TargetControlID
property of the ServHoverBehavior control. The ScriptPath
property contains the path to the MyHoverBehavior.js file. Note the two
properties HoverScript and UnhoverScript
are assigned to two strings that hold two JavaScript functions respectively.
In addition, we should notice that at the start up of the
web page we have to set the proper CSS style to the Panel control to make the
test result more attractive:
function pageLoad()
{
document.getElementById("<%=panel1.ClientID %>").className='start';
}
As for the two above-mentioned methods, Listing 6 gives
their simple programming.
Listing 6
function SetHoverCSS()
{
document.getElementById("<%=panel1.ClientID %>").className='hover';
}
function SetUnhoverCSS()
{
document.getElementById("<%=panel1.ClientID %>").className='start';
}
Easy enough, isn't it? When the mouse hovers over the Panel,
the style of the panel is set to "hover" (Figure 3) while when the
mouse leaves (unhovers) the Panel the style is set (restored) to "start"
(Figure 4). Here the two styles (hover and start) are both defined within file intro.css.
Figure 3 - When the mouse hovers over the Panel,
the style of the panel is set to "hover"
Figure 4 - When the mouse leaves the Panel, the
style of the panel is set to "start"
As we mentioned in the earlier articles, the <textarea>
(with id being "TraceConsole") at the bottom of the two snapshots
will facilitate the debugging of JavaScript files.