Recall that this script block takes the following two important actions: ❑ Calls the _initialize static method on the client-side PageRequestManager class to instantiate and initialize
Trang 1ASP.NET AJAX Client-Side PageRequestManager The last chapter followed the Page object through its life cycle phases to process the first request to
a Web page enabled for partial page rendering As you saw, the server response to this request contains a script block generated by the current server-side PageRequestManager instance Recall that this script block takes the following two important actions:
❑ Calls the _initialize static method on the client-side PageRequestManager class to instantiate and initialize the current client-side PageRequestManager instance
❑ Calls the _updateControls instance method on the current client-side
PageRequestManager instance, passing in four parameters:
❑ The first parameter is an array containing one string for each UpdatePanel server control on the current page This string consists of two substrings The first substring contains the letter t if the ChildrenAsTriggers property of the associated
UpdatePanel server control has been set to true and the letter f otherwise The second substring contains the value of the Unique ID property of the associated
UpdatePanel server control
❑ The second parameter is an array that contains the Unique ID property values of all server controls on the current page that cause synchronous page postbacks
❑ The third parameter is an array that contains the Unique ID property values of all server controls on the current page that cause asynchronous page postbacks
❑ The fourth parameter is a string that contains the asynchronous postback request timeout
Listing 22-1 presents an example of the script block rendered by the current server-side
PageRequestManager instance
Trang 2Listing 22-1: The Sample Script Block that Arrives on the Client Side as Part of the
In this chapter we’ll move on to the client side, where the server response — including this script block —
arrives As you can see, this script block automatically invokes the _intialize and _updateControls
methods of the client-side PageRequestManager Figure 22-1 depicts the instantiation and initialization
of the current PageRequestManager instance As you can see, this figure diplays the two method calls
I’ve discussed Note that this figure contains two dashed lines The top one represents the method calls
triggered by the call into the _initialize method of the PageRequestManager The bottom one
repre-sents the method calls triggered by the call into the _updateControls method I’ll discuss these two sets
of triggered method calls in the following sections, and update this figure with new method calls as we
move through the chapter
PageRequestManager Instantiation/InitializationPageRequestManager
Trang 3Listing 22-2: The _ initialize Static Method of the PageRequestManager Client Class
Sys.WebForms.PageRequestManager._initialize = function Sys$WebForms$PageRequestManager$_initialize(scriptManagerID, formElement){
Sys.WebForms.PageRequestManager._ensureSinglePageRequestManagerInstance();
Sys.WebForms.PageRequestManager._createPageRequestManagerInstance();
Sys.WebForms.PageRequestManager._initializePageRequestManagerInstance(
scriptManagerID, formElement);}
Note that this method takes two parameters The first is a string that contains the value of the Unique ID property of the current ScriptManager instance; the second references the form HTML element that contains the current ScriptManager instance
This method first calls the _ensureSinglePageRequestManagerInstance static method on the
PageRequestManager to ensure that the current page contains a single PageRequestManager instance
As the following code listing shows, _ensureSinglePageRequestManagerInstance calls the
getInstance static method on the client-side PageRequestManager to check whether the current page already contains an instance of the client-side PageRequestManager class If so, it raises an exception, because every page can contain only one instance of this class:
Sys.WebForms.PageRequestManager._ensureSinglePageRequestManagerInstance = function Sys$WebForms$PageRequestManager$_ ensureSinglePageRequestManagerInstance(){
if (Sys.WebForms.PageRequestManager.getInstance()) throw Error.invalidOperation(Sys.WebForms.Res.PRM_CannotRegisterTwice);
Sys.WebForms.PageRequestManager._createPageRequestManagerInstance = function Sys$WebForms$PageRequestManager$_createPageRequestManagerInstance(){
Sys.WebForms.PageRequestManager._instance = new Sys.WebForms.PageRequestManager();
}
Finally, the _initialize method calls the _initializePageRequestManagerInstance static method
to initialize the newly created PageRequestManager instance As the following code listing shows, this method calls the _initializeInternal private instance method on the newly instantiated client-side
PageRequestManager , passing in the value of the Unique ID property of the ScriptManager server control and the reference to the form HTML element of the current page:
Trang 4Listing 22-3 presents the internal implementation of the getInstance static method of the client-side
PageRequestManager class As you can see, this method returns the value of the _instance static field
of the PageRequestManager client class
If you need to access this instance from your client-side code, call the getInstance static method
on the client-side PageRequestManager class to return a reference to the current client-side
PageRequestManager instance
Figure 22-2
PageRequestManager Instantiation/InitializationPageRequestManager
_ensureSinglePageRequestManagerInstance ( ) getInstance ( )
_createPageRequestManagerInstance ( ) _initializePageRequestManagerInstance (scriptManagerUniqueID, formElement) _initializeInternal (scriptManagerUniqueID, formElement) _initialize(scriptManagerUniqueID, formElement)
_updateControls([…], […], […], asyncPostBackTimeout)
Trang 5Listing 22-3: The get Instance Static Method of the PageRequestManager Client Class
Sys.WebForms.PageRequestManager.getInstance = function Sys$WebForms$PageRequestManager$getInstance(){
HTML element However, only one of these <form> HTML elements can have the
runat=”server” attribute The ASP.NET framework represents this <form> HTML element with an instance of the HtmlForm server control The _form field of the client-side
❑ _oldUpdatePanelIDs : This field is an array that contains the values of the Unique ID properties
of all UpdatePanel server controls on the current page before update
❑ _childUpdatePanelIDs : This field is an array that contains the values of the Unique ID properties of all child UpdatePanel server controls after update
❑ _panelsToRefreshIDs : This field is an array that contains the values of the Unique ID properties
of all parent UpdatePanel server controls that need refreshing
❑ _updatePanelHasChildrenAsTriggers : This field is an array that contains the values of the Unique ID properties of all UpdatePanel server controls on the current page whose
ChildrenAsTriggers Boolean property have been set to true
❑ _asyncPostBackControlIDs : This field is an array that contains the values of the Unique ID properties of all server controls on the current page that cause asynchronous page postbacks
❑ _asyncPostBackControlClientIDs : This field is an array that contains the values of the
ClientID properties of all server controls on the current page that cause asynchronous page postbacks
❑ _postBackControlIDs : This field is an array that contains the values of the Unique ID properties of all server controls on the current page that cause synchronous page postbacks
❑ _postBackControlClientIDs : This field is an array that contains the values of the ClientID properties of all server controls on the current page that cause synchronous page postbacks
Trang 6❑ _scriptManagerID : This field contains the value of the Unique ID property of the current
ScriptManager server control
❑ _pageLoadedHandler : This field references the delegate registered as an event handler for the
load event of the window object
❑ _additionalInput : This field contains additional optional information
❑ _onsubmit : This field references the original onsubmit method of the form DOM element that
the _form field references As you’ll see later, the client-side PageRequestManager instance
replaces this method with another method when it needs to make an asynchronous page
post-back to the server Before replacing this method, the current client-side PageRequestMananger
instance stores the function in the _onsubmit field so it can be used later when the page needs
to make a synchronous page postback
❑ _onSubmitStatements : This field is an array that contains dynamically added form submit
statements
❑ * _originalDoPostBack : This field references the _doPostBack JavaScript function that
per-forms a regular synchronous page postback to the server As you’ll see later, the client-side
PageRequestManager instance replaces this JavaScript function with the one that performs an
asynchronous page postback to the server when PageRequestManager needs to make an
asyn-chronous postback request Before replacing the _doPostBack JavaScript function, the current
client-side PageRequestManager instance stores the function in the _originalDoPostBack
field so it can be used later when the page needs to make a synchronous page postback
❑ _postBackSettings : This field references an object literal with three name/value pairs
that describe the postback settings for the postback request that the current client-side
PageRequestManager instance is about to make to the server The name part of the first name/
value pair is the keyword async , and the value part is a Boolean value that specifies whether
the current postback request is asynchronous The name part of the second name/value pair
is the keyword panel ID , and the value part is a string that contains the value of the Unique ID
property of the UpdatePanel server control whose trigger triggered the current asynchronous
page postback The name part of the third name/value pair is the keyword sourceElement ,
and the value part references the DOM element that triggered the asynchronous page postback
❑ _request : This field references the WebRequest object that represents the current asynchronous
page postback request
❑ _onFormSubmitHandler : This field references the delegate that represents the _onFormSubmit
method of the current PageRequestManager instance As you’ll see later, this instance registers
this delegate as an event handler for the submit event of the form DOM element referenced
by the _form field
❑ _onFormElementClickHandler : This field references the delegate that represents the
_onFormElementClick method of the current PageRequestManager instance As you’ll see
later, this instance registers this delegate as an event handler for the click event of the form
DOM element referenced by the _form field
❑ _onWindowUnloadHandler : This field references the delegate that represents the
_onWindowUnload method of the current PageRequestManager instance As you’ll see
later, this instance registers this delegate as an event handler for the unload event of the form
DOM element referenced by the _form field
❑ _asyncPostBackTimeout : This field is a string that contains the asynchronous page postback
request timeout
Trang 7❑ _controlIDToFocus : This field is a string that contains the value of the Unique ID property of the server control that has the mouse focus
❑ _scrollPosition : This field references an object literal with two name/value pairs that describe the current position of the scroll The name part of the first name/value pair is the keyword x , and the value part is an integer that specifies the x coordinate of the scroll bar The name part of the second name/value pair is the keyword y , and the value part is an integer that specifies the y coordinate of the scroll bar
❑ _dataItems : This field references a dictionary of data items
❑ _response : This field references the WebRequestExecutor object responsible for executing the current asynchronous page postback request
❑ _processingRequest : This field is a Boolean value that specifies whether the current
PageRequestManager is processing the server response
❑ _scriptDisposes : This field references a dictionary of script disposes
Listing 22-4: The Constructor of the PageRequestManager Client Class
Sys.WebForms.PageRequestManager = function Sys$WebForms$PageRequestManager(){
Trang 8PageRequestManager instance requires a good understanding of the two common types of page postback
Therefore, before diving into the implementation of this method, we need to study these two different types
The first relies on the Submit button As you know, when the user clicks the Submit button, the form
DOM element raises the submit event and consequently invokes the onsubmit event handler If the
onsubmit event handler does not return false , the browser takes these steps:
1 Collects the names and values of the form elements
2 Generates a list of items separated by the & character, where each item contains the name and
value of a form element Each item consists of two parts separated by the equals sign ( = ), the
first containing the name of the form element and the second containing the value
3 Creates an HTTP POST request
4 Adds the list of items to the body of the request
5 Sets the request headers, such as Content-Type, Content-Length, Host, etc
6 Submits the request to the server synchronously
The onsubmit event handler normally validates the values of the form elements and returns false to
cancel the form submission if the validation fails
The main problem with the first type of page postback is its strict reliance on the Submit button for form
submission There are times when the form must be submitted via DOM elements other than the Submit
button For example, you may want the form submission to occur when the user selects an item from a
certain HTML element This is where the second type of page postback comes into play
This type relies on the doPostBack JavaScript function The ASP.NET server controls, such as the
DropDownList , register this JavaScript function as an event handler for one of their events For example,
the DropDownList server control registers the _doPostBack JavaScript function as event handler for the
onchange event of the <select> HTML element associated with the server control if the AutoPostBack
property of the server control is set to true
Listing 22-5 contains the definition of the _doPostBack JavaScript function Since this JavaScript
func-tion is a global one, it is automatically considered as a method on the window object As you can see,
_doPostBack takes two arguments The first is the value of the Unique ID property of the server control
that caused the postback For example, in the case of the DropDownList server control, this will be the
value of the Unique ID property of the DropDownList control itself The second argument is optional In
the case of the DropDownList server control, this will be the value of the value property of the selected
<option> element of the <select> element associated with the server control
As you can see from Listing 22-5 , the _doPostBack JavaScript function takes the following steps First, it
invokes the onsubmit event handler Recall that this event handler normally validates the values of the
form elements and returns false if the validation fails As Listing 22-5 shows, if the onsubmit event
handler does not return false , the _doPostBack JavaScript function assigns its first parameter to the
value property of a hidden field named EVENTTARGET and its second parameter to the value
Trang 9property of a hidden field named EVENTARGUMENT For example, in the case of the DropDownList server control, the _doPostBack JavaScript function assigns the Unique ID property value of the server control to the value property of the EVENTTARGET hidden field and the value of the value property
of the selected option subelement of the select element associated with the server control to the value property of the EVENTARGUMENT hidden field
theForm. EVENTTARGET.value = eventTarget;
theForm. EVENTARGUMENT.value = eventArgument;
Finally, the _doPostBack JavaScript function invokes the submit method on the form DOM element to submit the values of the form elements to the server When the submit method is invoked, under the hood, the browser takes these steps:
1 Collects the names and values of the form elements
2 Generates a list of items separated by the & character, where each item contains the name and value of a form element Each item consists of two parts separated by the equals sign ( = ), the first containing the name of the form element and the second containing the value
3 Creates an HTTP POST request
4 Adds to the body of the request the list of items shown in Step 2
5 Sets the request headers, such as Content-Type, Content-Length, Host, etc
6 Submits the request to the server synchronously
Note that the preceding six steps are the same ones the browser takes for the first type of page postback
— that is, the page postback via the Submit button In other words, both the page postback via the Submit button and the page postback via the _doPostBack JavaScript function rely on the browser to take these steps
Listing 22-5: The Standard do PostBack JavaScript Function
<script type=’text/javascript’>
var theForm = document.forms[‘Form1’];
if (!theForm) theForm = document.Form1;
function doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm. EVENTTARGET.value = eventTarget;
theForm. EVENTARGUMENT.value = eventArgument;
theForm.submit();
} }// >
</script>
Both the page postback via the Submit button and page postback via the _doPostBack JavaScript tion suffer from the following fundamental shortcomings:
Trang 10func-❑ The browser submits the request to the server synchronously A synchronous request is blocking ,
meaning that the end user cannot interact with the page until the server response arrives This
dramatically degrades the responsiveness, performance, and usability of a Web application that
relies heavily on normal synchronous page postbacks
❑ In both types of page postbacks, when the server response finally arrives, the entire page reloads
even though only a small portion of the page requires refreshing This also dramatically
de-grades the responsiveness, performance, and usability of a graphic-heavy Web page, which
takes a lot of time to re-render
As you’ll see in this chapter, the current PageRequestManager instance resolves both of these problems,
as follows:
❑ Unlike page postback via the Submit button or the _doPostBack JavaScript function, it does
not rely on the browser’s default synchronous form submission Instead, the current
PageRequestManager instance uses the ASP.NET AJAX client-server communication layer
discussed in previous chapters to make asynchronous page postback requests to the server
❑ Unlike page postback via the Submit button or the _doPostBack JavaScript function, it does not
rely on the browser’s default rendering mechanism, which re-renders the entire page when the
server response arrives Instead, the current PageRequestManager instance uses the ASP.NET
AJAX client-side framework to refresh only those parts of the page that need refreshing
Now that you have a good understanding of the two main types of page postbacks and their
shortcom-ings, you’re ready to dive into the internal implementation of the _initializeInternal method of the
PageRequestManager , as shown in Listing 22-6
Listing 22-6: The _ initialize Internal Intance Method of the PageRequestManager
As you can see, this method takes two arguments The first is a string that contains the value of the
UniqueID property of the ScriptManager server control The second references the form DOM element
of the current page The method assigns the following two parameters to the _scriptManagerID and
_form private fields of the current PageRequestManager instance:
this._scriptManagerID = scriptManagerID;
this._form = formElement;
Trang 11Next, the _initializeInternal method calls the _detachAndStoreOriginalFormOnSubmit method shown in the following code listing As you can see, this method detaches the onsubmit method from the form DOM element and stores it in a local field named _onsubmit for future reference:
function Sys$WebForms$PageRequestManager$_detachAndStoreOriginalFormOnSubmit(){
function Sys$WebForms$PageRequestManager$_registerHandlerForFormSubmitEvent (){
this._onFormSubmitHandler = Function.createDelegate(this, this._onFormSubmit);
Sys.UI.DomEvent.addHandler(this._form, ‘submit’, this._onFormSubmitHandler);
}
Recall that page postback via the Submit button causes the form DOM element to fire its submit event Since the current PageRequestManager instance has registered the _onFormSubmitHandler delegate for this event, this delegate and consequently the _onFormSubmit method of the current PageRequestManager instance are automatically invoked This allows the current PageRequestManager instance to take complete control over the first type of page postback mechanism before the page is actually posted back to the server
As you’ll see later, the _onFormSubmit method of the current PageRequestManager instance will first determine whether the form submission must be done asynchronously If so, it will bypass the browser’s default synchronous form submission and use the ASP.NET AJAX client-server communication layer discussed in previous chapters to make an asynchronous page postback to the server If the _onFormSubmit method of the current PageRequestManager instance comes to the conclusion that the form must be submitted synchronously, the method gets out of the way and allows the browser to take over the form sub-mission and submit the form synchronously
Now back to the discussion of the implementation of the _initializeInternal method of the
PageRequestManager Next, this method calls the _detachAndStoreOriginalDoPostBack method shown in the following code listing As you can see, this method detaches the _doPostBack JavaScript function shown in Listing 22-5 from the window object and stores it in the _originalDoPostBack field
of the current PageRequestManager instance for future reference:
function Sys$WebForms$PageRequestManager$_detachAndStoreOriginalDoPostBack(){
Trang 12fol-function Sys$WebForms$PageRequestManager$_attachNewDoPostBack()
{
window. doPostBack = Function.createDelegate(this, this._doPostBack);
}
Recall that the second type of page postback invokes the _doPostBack method of the window object to
submit the form to the server Since the current PageRequestManager instance has replaced the original
_doPostBack method (that is, the one shown in Listing 22-5 ) with the delegate that represents
the _doPostBack method of the current PageRequestManager instance, when a server control such as
DropDownList calls the _doPostBack method of the window object, this delegate and consequently the
_doPostBack method of the current PageRequestManager instance will be called instead of the
origi-nal _doPostBack method shown in Listing 22-5 This allows the current PageRequestManager instance
to take complete control of the second type of page postback mechanism before the page is actually
posted back to the server As you’ll see later in this chapter, the _doPostBack method of the current
PageRequestManager instance will first determine whether the form submission must be done
asyn-chronously If so, it will bypass the browser’s default synchronous form submission and use the ASP
NET AJAX client-server communication layer discussed in previous chapters to make an asynchronous
page postback to the server If the _doPostBack method of the current PageRequestManager instance
comes to the conclusion that the form must be submitted synchronously, the method gets out of the way
and allows the browser to take over the form submission and submit the form synchronously
Now back to the discussion of the implementation of the _initializeInternal method Next, this
method calls the _registerHandlerForWindowLoadEvent method shown in the following code listing
As you can see, this method first creates a delegate that represents the _pageLoadedInitialLoad method
of the current PageRequestManager instance, and then registers this delegate as an event handler for the
load event of the window object Therefore, when the window raises its load event, this delegate and
conse-quently the _pageLoadedInitialLoad method of the current PageRequestManager instance are invoked:
Next, the _initializeInternal method calls the _registerHandlerFormClickEvent method
shown in the following code listing As you can see, this method first creates a delegate that represents
the _onFormElementClick method of the current PageRequestManager instance, and then registers
this delegate as an event handler for the click event of the form element:
Then the _initializeInternal method calls the _registerHandlerForWindowUnloadEvent
method shown in the following code listing As you can see, this method first creates a delegate that
rep-resents the _onWindowUnload method of the current PageRequestManager instance, and then registers
this delegate as an event handler for the unload event of the window object:
Trang 13function Sys$WebForms$PageRequestManager$_registerHandlerForWindowUnloadEvent(){
this._onWindowUnloadHandler = Function.createDelegate(this, this._onWindowUnload);
Sys.UI.DomEvent.addHandler(window, ‘unload’, this._onWindowUnloadHandler);
}
Finally, the method calls the _storeOriginalFormAction method shown in the following code listing
As you can see, this method stores the value of the action property of the form DOM element in a custom property on the form named _initialAction for future reference As you’ll see later, the current PageRequestManager instance uses the initial action value to determine whether a given request is a cross-page postback
function Sys$WebForms$PageRequestManager$_storeOriginalFormAction(){
this._form._initialAction = this._form.action;
}
Figure 22-3 updates Figure 22-2 with the method calls that the _initializeInternal method triggers Note that Figure 22-3 inherits the bottom dashed line from Figure 22-2 Recall that this dashed line repre-sents the method calls triggered by the call into the _updateControls method
PageRequestManager Instantiation/InitializationPageRequestManager
_ensureSinglePageRequestManagerInstance ( ) getInstance ( )
_createPageRequestManagerInstance ( ) _initializePageRequestManagerInstance (scriptManagerUniqueID, formElement) _initializeInternal (scriptManagerUniqueID, formElement) _detachAndStoreOriginalFormOnSubmit ( ) _registerHandlerForFormSubmitEvent ( ) _detachAndStoreOriginalDoPostBack ( ) _attachNewDoPostBack ( ) _registerHandlerForWindowLoadEvent ( ) _registerHandlerForFormClickEvent ( ) _registerHandlerForWindowUnloadEvent ( ) _storeOrigianlFormAction ( )
_initialize(scriptManagerUniqueID, formElement)
_updateControls([…], […], […], asyncPostBackTimeout)
Figure 22-3
Trang 14_ update Controls
Listing 22-7 presents the internal implementation of the _updateControls method of the
PageRequestManager This method takes the following four parameters:
❑ updatePanelIDs : This parameter is an array that contains the values of the Unique ID
proper-ties of all the UpdatePanel server controls on the current page
❑ asyncPostBackControlIDs : This parameter is an array that contains the values of the
Unique ID properties of all the server controls on the current page that cause asynchronous page
postbacks
❑ postBackControlIDs : This parameter is an array that contains the values of the Unique ID
properties of all the server controls on the current page that cause synchronous page postbacks
❑ asyncPostBackTimeout : This parameter is a string that contains the asynchronous page
post-back request timeout
Listing 22-7: The _ update Controls Method of the PageRequestManager
this._updatePanelIDs = new Array(updatePanelIDs.length);
this._updatePanelClientIDs = new Array(updatePanelIDs.length);
this._updatePanelHasChildrenAsTriggers = new Array(updatePanelIDs.length);
for (var i = 0; i < updatePanelIDs.length; i++)
Trang 15for (var i = 0; i < asyncPostBackControlIDs.length; i++) {
Array.add(this._asyncPostBackControlIDs, asyncPostBackControlIDs[i]);
Array.add(this._asyncPostBackControlClientIDs, this._uniqueIDToClientID(asyncPostBackControlIDs[i]));
} this._postBackControlIDs = [];
}}
The _updateControls method takes the following steps First, it instantiates the _updatePanelIDs ,
_updatePanelClientIDs , and _updatePanelHasChildrenAsTriggers array fields of the current
PageRequestManager instance:
this._updatePanelIDs = new Array(updatePanelIDs.length);
this._updatePanelClientIDs = new Array(updatePanelIDs.length);
this._updatePanelHasChildrenAsTriggers = new Array(updatePanelIDs.length);
Next, it iterates through the UniqueID property values in the updatePanelIDs parameter and takes the following actions for each enumerated UniqueID property value (Keep in mind that this value consists
of two substrings, the first containing the character t or f , and the second containing the actual
UniqueID property value):
❑ As mentioned, the current PageRequestManager instance contains a private array field named
_updatePanelIDs that contains the Unique ID property values of all the UpdatePanel server controls on the current page The _updateControls method retrieves the second substring of the enumerated value and adds it to the _updatePanelIDs array:
this._updatePanelIDs[i] = updatePanelIDs[i].substr(1);
❑ The current PageRequestManager instance also contains a private array field named
_updatePanelClientIDs that contains the ClientID property values of all the
UpdatePanel server controls on the current page The _updateControls method calls the
_uniqueIDToClientID method to return the ClientID property value associated with the UniqueID property value and adds this ClientID property value to the
_updatePanelClientIDs array:
this._updatePanelClientIDs[i] = this._uniqueIDToClientID(this._updatePanelIDs[i]);
❑ The current PageRequestManager instance contains a private Boolean array field named
_updatePanelHasChildrenAsTriggers that contains one Boolean value for each UpdatePanel server control on the page, which specifies whether its child server controls trigger partial page updates The _updateControls method retrieves the first substring of the enumerated value If this substring contains the character t , asynchronous updates of the server control are triggered
by the child controls of the UpdatePanel server control whose UniqueID property is given by the second substring, and the _updateControls method adds the Boolean value of true to the
_updatePanelHasChildrenAsTriggers collection Otherwise it adds false
Trang 16this._updatePanelHasChildrenAsTriggers[i] =
(updatePanelIDs[i].charAt(0) === ‘t’);
❑ The current PageRequestManager instance also contains an integer field named
_asyncPostBackTimeout that specifies the timeout (in seconds) for all asynchronous page
postback requests The _updateControls method converts to seconds the value passed into it
as its last parameter, and assigns the value to this field:
this._asyncPostBackTimeout = asyncPostBackTimeout * 1000;
Next, the _updateControls method iterates through the Unique ID property values in the
asyncPostBackControlIDs array and takes these actions for each value:
❑ The current PageRequestManager instance contains a private array field named
_asyncPostBackControlIDs that contains the Unique ID property values of all the server
controls on the current page that trigger asynchronous page postbacks The _updateControls
method adds the enumerated Unique ID property value to this array field:
Array.add(this._asyncPostBackControlIDs, asyncPostBackControlIDs[i]);
❑ The current PageRequestManager instance contains a private array field named
_asyncPostBackControlClientIDs that contains the ClientID property values of all
the server controls on the current page that trigger asynchronous page postbacks The
_updateControls method first calls the _uniqueIDToClientID method to return the
ClientID property value associated with the enumerated Unique ID property value, and then
adds this return value to this array field:
Array.add(this._asyncPostBackControlClientIDs,
this._uniqueIDToClientID(asyncPostBackControlIDs[i]));
Next, the _updateControls method iterates through the Unique ID property values in the
postBackControlIDs array and takes these actions for each value:
❑ The current PageRequestManager instance contains a private array field named
_postBackControlIDs that contains the UniqueID property values of all the server
controls on the current page that trigger synchronous page postbacks The _updateControls
method adds the enumerated UniqueID property value to this array field:
Array.add(this._postBackControlIDs, postBackControlIDs[i]);
❑ The current PageRequestManager instance contains a private array field named
_postBackControlClientIDs that contains the ClientID property values of all the server
controls on the current page that trigger asynchronous page postbacks The _updateControls
method first calls the _uniqueIDToClientID method to return the ClientID property value
associated with the enumerated UniqueID property value, and then adds this return value to
this array field:
Array.add(this._postBackControlClientIDs,
this._uniqueIDToClientID(postBackControlIDs[i]));
As Listing 22-8 shows, the _uniqueIDToClientID method takes an UniqueID value as its argument
Trang 17The UniqueID and ClientID property values of an ASP.NET server control are read-only, which means that only the ASP.NET can set their values The UniqueID property value of a server control is a string that consists of two substrings separated by the dollar sign ( $ ), the first containing the value of the
ID property of the server control and the second containing the value of the UniqueID property of the parent of the server control The ClientID property value of a server control is a string that consists of two substrings separated by the underscore character ( _ ), the first containing the value of the ID prop-erty of the server control and the second containing the value of the ClientID property of the parent of the server control As you can see, the only difference between the UniqueID and the ClientID property values of a server control is the separator That is why the _uniqueIDToClientID method replaces the dollar signs with the underscore characters to arrive at the ClientID property value
Listing 22-8: The _ unique IDToClientID Method of the PageRequestManager
function Sys$WebForms$PageRequestManager$_uniqueIDToClientID(uniqueID){
// Convert unique IDs to client IDs by replacing all ‘$’ with ‘_’
return uniqueID.replace(/\$/g, ‘_’);
}
Figure 22-4 updates Figure 22-3 with the new method calls
PageRequestManager Instantiation/InitializationPageRequestManager
_updatePanelClientIDs _updatePanelIDs _updatePanelHasChildrenAs
_asyncPostBackControlIDs
_postBackControlClientIDs
_asyncPostBackControlClientIDs
_asyncPostBackTimeout _postBackControlIDs
_ensureSinglePageRequestManagerInstance ( ) getInstance ( )
_createPageRequestManagerInstance ( ) _initializePageRequestManagerInstance (scriptManagerUniqueID, formElement) _initializeInternal (scriptManagerUniqueID, formElement) _detachAndStoreOriginalFormOnSubmit ( ) _registerHandlerForFormSubmitEvent ( ) _detachAndStoreOriginalDoPostBack ( ) _attachNewDoPostBack ( ) _registerHandlerForWindowLoadEvent ( ) _registerHandlerForFormClickEvent ( ) _registerHandlerForWindowUnloadEvent ( ) _storeOrigianlFormAction ( )
_initialize(scriptManagerUniqueID, formElement)
add ( ) add ( ) add ( )
add ( ) add ( )
add ( )
add ( )
add ( ) _updateControls([…], […], […], asyncPostBackTimeout)
Figure 22-4
Trang 18The _ page LoadedInitialLoad Method of the Client-Side
PageRequestManager
When the current page is finally loaded, the window object raises the load event and calls the
_pageLoadedHandler delegate, which in turn calls the _pageLoadedInitialLoad instance method
of the current client-side PageRequestManager instance, as shown in Listing 22-9
Listing 22-9: The _ page LoadedInitialLoad Method of the PageRequestManager
As you can see, the _pageLoadedInitialLoad method calls the _pageLoaded method of the current
client-side PageRequestManager instance, passing in true as its argument
The _ page Loaded Method of the Client-Side
// If this isn’t the first page load (i.e we are doing an async postback), we
// need to re-raise the Application’s load event
Sys.Application.raiseLoad();
}
}
This method first calls the _get_eventHandlerList method to return a reference to the
EventHandlerList object that contains all the event handlers registered for the events of the current
client-side PageRequestManager instance, and then calls the getHandler method on the
EventHandlerList to return a reference to the JavaScript function whose invocation automatically
Trang 19invokes all the event handlers registered for the pageLoaded event of the current client-side
PageRequestManager instance I’ll discuss this event later in the chapter
var handler = this._get_eventHandlerList().getHandler(“pageLoaded”);
Next, the _pageLoaded method calls the _getPageLoadedEventArgs method to create and return a
PageLoadedEventArgs object As you’ll see later, the PageLoadedEventArgs class is the event data class for the pageLoaded event of the client-side PageRequestManager instance
var pageLoadedEventArgs = this._getPageLoadedEventArgs(initialLoad);
Then it calls the JavaScript function, passing in a reference to the current client-side PageRequestManager instance and a reference to the PageLoadedEventArgs instance This JavaScript function in turn calls all the event handlers registered for the pageLoaded event of the current client-side PageRequestManager instance, passing in the same two references
if (handler) handler(this, this._getPageLoadedEventArgs(initialLoad));
This enables you to perform application-specific tasks by registering an event handler for the
pageLoaded event of the current PageRequestManager instance
Figure 22-5 updates Figure 22-4 with the latest method calls This wraps up our discussion of the instantiation/initialization process of the current client-side PageRequestManager instance Keep in mind that this process occurs only for the first request and subsequent normal synchronous page post-back requests In other words, it does not occur for subsequent asynchronous page postback requests
In summary, the previous chapter followed the first request from the time it arrived in ASP.NET to the time the server response text, including the PageRequestManager instantiation/initialization script block — such as the one shown in Listing 22-1 — was sent back to the client The previous sections of this chapter then followed this server response text from the time it arrived on the client side to the time the instantiation and initialization of the current PageRequestManager instance were completed
Now the current PageRequestManager instance is sitting there waiting for the first or second type of page postback to occur Recall that there are two types of page postbacks, via the Submit button and via the _doPostBack method of the window object As we discussed earlier, as soon as the first type of page postback occurs, the _onFormSubmit method of the current PageRequestManager instance will inter-cept it before the page is actually posted back to the server; and as soon as the second type of page post-back occurs, the _doPostBack method of the current PageRequestManager instance will intercept it before the page is actually posted back to the server Both the _onFormSubmit and _doPostBack meth-ods of the current PageRequestManager instance will first determine whether the page postback must
be done asynchronously If so, both methods bypass the browser’s default synchronous form submission and use the ASP.NET AJAX client-server communication layer (discussed in previous chapters) to sub-mit the form asynchronously If these methods determine that the page postback must be done synchro-nously, they simply get out of the way and let the browser’s default synchronous form submission take over and submit the form synchronously
Trang 20The page Loaded Event
The previous sections followed the current client-side PageRequestManager instance through its
instantiation/initialization life cycle phases As you can see from Figure 22-5 , the current client-side
PageRequestManager instance fires its pageLoaded event at the end of its instantiation/initialization
phase to enable you to perform application-specific tasks that must be performed right after the current
client-side PageRequestManager instance is instantiated and initialized
The client-side PageRequestManager class uses the standard ASP.NET AJAX event-implementation
pattern to implement its pageLoaded event as follows:
1 The PageRequestManager class defines a collection property of type EventHandlerList to store
all the event handlers registered for the events of the current client-side PageRequestManager
instance
2 It defines a getter method that returns a reference to this EventHandlerList object:
PageRequestManager Instantiation/InitializationPageRequestManager
_updatePanelClientIDs _updatePanelIDs _updatePanelHasChildrenAs
_asyncPostBackControlIDs
_postBackControlClientIDs
_asyncPostBackControlClientIDs
window EventHandlerList
_asyncPostBackTimeout _postBackControlIDs
_ensureSinglePageRequestManagerInstance ( ) getInstance ( )
_createPageRequestManagerInstance ( ) _initializePageRequestManagerInstance (scriptManagerUniqueID, formElement) _initializeInternal (scriptManagerUniqueID, formElement) _detachAndStoreOriginalFormOnSubmit ( ) _registerHandlerForFormSubmitEvent ( ) _detachAndStoreOriginalDoPostBack ( ) _attachNewDoPostBack ( ) _registerHandlerForWindowLoadEvent ( ) _registerHandlerForFormClickEvent ( ) _registerHandlerForWindowUnloadEvent ( ) _storeOrigianlFormAction ( )
_pageLoaded ( )
_initialize(scriptManagerUniqueID, formElement)
add ( ) add ( ) add ( )
add ( ) add ( )
_updateControls([…], […], […], asyncPostBackTimeout)
Figure 22-5
Trang 21function Sys$WebForms$PageRequestManager$_get_eventHandlerList(){
if (!this._events) this._events = new Sys.EventHandlerList();
return this._events;
}
3 It defines a method named add_pageLoaded that enables you to register event handlers for the
pageLoaded event of the current client-side PageRequestManager instance As the following code fragment shows, this method first calls the get_eventHandlerList method on the current
PageRequestManager instance to return a reference to the EventHandlerList object Then it calls the addHandler method on this EventHandlerList object to register the specified handler
as an event handler for the pageLoaded event of the current PageRequestManager instance:
function Sys$WebForms$PageRequestManager$add_pageLoaded(handler){
implementation of the PageLoadedEventArgs class
Listing 22-11: The Internal Implementation of the Page LoadedEventArgs Class
Sys.WebForms.PageLoadedEventArgs = function Sys$WebForms$PageLoadedEventArgs(panelsUpdated, panelsCreated, dataItems){
/// <param name=”panelsUpdated” type=”Array”></param>
/// <param name=”panelsCreated” type=”Array”></param>
/// <param name=”dataItems” type=”Object” mayBeNull=”true”></param>
Trang 22As you can see, the constructor of the PageLoadedEventArgs class takes three parameters The first
is an array that contains the list of updated UpdatePanel server controls on the current page, the
second is an array that contains the list of newly created UpdatePanel server controls, and the last is
optional The last parameter is null when the pageLoaded event is raised at the end of the
instantiation/initialization of the current PageRequestManager instance However, as you’ll see in the
following chapters, the current client-side PageRequestManager instance also raises the pageLoaded
event when it is processing the server response to an asynchronous page postback request where the last
parameter of the constructor of the PageLoadedEventArgs class comes into play
As you can see from Listing 22-11 , the constructor of the PageLoadedEventArgs class stores its
parame-ters in private fields named _panelsUpdated , _panelsCreated , and _dataItems Note that the
PageLoadedEventArgs class exposes three getters named get_panelsUpdated , get_panelsCreated ,
and get_dataItems , that return these private fields
Now let’s revisit Listing 22-10 , as shown again in the following code listing:
Trang 23if (!initialLoad) {
// If this isn’t the first page load (i.e we are doing an async postback), we // need to re-raise the Application’s load event
Sys.Application.raiseLoad();
}}
As you can see, for the highlighted portion of the preceding code listing, this method invokes the
_getPageLoadedEventArgs(initialLoad) internal method on the current PageRequestManager instance to instantiate and return an instance of the PageLoadedEventArgs class, which is then passed into the event handlers registered for the pageLoaded event of the current PageRequestManager instance (I’ll present and discuss the internal implementation of the _getPageLoadedEventArgs method in Chapter 28 )
Using the page Loaded Event
As I mentioned earlier, the current client-side PageRequestManager instance fires its pageLoaded event
at the end of its instantiation/initialization process to enable you to perform application-specific tasks that must be performed right after the current PageRequestManager instance is instantiated and initial-ized Follow these steps to ensure that your required application-specific logic is executed right after the current PageRequestManager instance is instantiated and initialized:
1 If your required application-specific logic is encapsulated in a method of an ASP.NET AJAX
cli-ent class, invoke the createDelegate static method on the Function to instantiate a delegate that represents this method If your required application-specific logic is not already encapsu-lated in a method of an ASP.NET AJAX client class, write a new JavaScript function that encap-sulates this logic
2 Implement a JavaScript function that performs the following tasks:
❑ Invokes the getInstance static method on the client-side PageRequestManager class to return a reference to the current client-side PageRequestManager instance
❑ Invokes the add_pageLoaded method on the current client-side PageRequestManager instance to register the delegate or the JavaScript function from Step 1 as the event handler for the pageLoaded event of the current client-side PageRequestManager instance
3 Register the JavaScript function from Step 3 as an event handler for the load event of the
window object
Listing 22-12 contains a page that uses this recipe If you run this page, you should see the results shown
in Figures 22-6 and 22-7 As Figure 22-6 shows, this page consists of a parent UpdatePanel server control that contains two child UpdatePanel server controls: one is added statically and the other is added dynamically — that is, via code When you run this page, the page also displays the popup shown in Figure 22-7 As you can see, this popup contains a message that displays, right after the current client-side
PageRequestManager instance is instantiated and initialized, some of the information that is available to
an event handler registered for the pageLoaded event What you do with this information is completely
up to you Your event handler can use it information to perform application-specific tasks that must be performed right after the current client-side PageRequestManager instance is instantiated and initialized
Trang 24Listing 22-12: A Page that Uses the page Loaded Event to Execute
TableHeaderCell headerCell = new TableHeaderCell();
headerCell.Text = “Dynamic Child UpdatePanel Control”;
Label label = (Label)Page.FindControl(“DynamicChildUpdatePanelLabel”);
label.Text = “UpdatePanel refreshed at “ + DateTime.Now.ToString() +
Trang 25<title>Untitled Page</title>
<script type=”text/javascript” language=”javascript”>
window.onload = function () {
var panelsUpdated = e.get_panelsUpdated();
var panelsCreated = e.get_panelsCreated();
var dataItems = e.get_dataItems();
var builder = new Sys.StringBuilder();
Trang 26<form id=”form1” runat=”server”>
<asp:ScriptManager ID=”ScriptManager1” runat=”server” />
Trang 27<asp:Button ID=”StaticChildUpdatePanelTrigger” runat=”server”
Text=”Static Child UpdatePanel Trigger” Width=”100%” />
to the ParentUpdatePanelLabel and StaticChildUpdatePanelLabel server controls, and then sets the values of their Text properties to the current time:
Label parentUpdatePanelLabel = (Label)Page.FindControl(“ParentUpdatePanelLabel”);
parentUpdatePanelLabel.Text = “UpdatePanel refreshed at “ + DateTime.Now.ToString();
Label staticChildUpdatePanelLabel = (Label)Page.FindControl(“StaticChildUpdatePanelLabel”);staticChildUpdatePanelLabel.Text = “UpdatePanel refreshed at “ +
DateTime.Now.ToString();
Trang 28Next, the Page_Load method instantiates an UpdatePanel server control and sets its ID property value:
UpdatePanel dynamicChildUpdatePanel = new UpdatePanel();
Next, it instantiates a TableRow server control to represent the header of the table:
TableRow headerRow = new TableRow();
table.Rows.Add(headerRow);
TableHeaderCell headerCell = new TableHeaderCell();
headerCell.Text = “Dynamic Child UpdatePanel Control”;
headerRow.Cells.Add(headerCell);
Figure 22-6
Trang 29Then it creates another TableRow server control with two cells that contain a Label and a Button server control, respectively:
TableRow bodyRow = new TableRow();
Trang 30Note that the ClickCallback method is registered as an event handler for the Click event of the
Button server control Next, the Page_Load method adds the Table server control to the Controls
collection of the ContentTemplateContainer property of the UpdatePanel server control:
dynamicChildUpdatePanel.ContentTemplateContainer.Controls.Add(table);
As Listing 22-12 shows, the client-side script block consists of two parts The first part registers the
following JavaScript function as an event handler for the load event of the window object:
As you can see from the code fragment, this JavaScript function first calls the getInstance static
method on the client-side PageRequestManager class to return a reference to the current client-side
PageRequestManager instance:
var prm = Sys.WebForms.PageRequestManager.getInstance();
Next, the function invokes the add_pageLoaded method on the current PageRequestManager instance
to register the pageLoadedHandler JavaScript function as an event handler for the pageLoaded event
of the current PageRequestManager instance:
prm.add_pageLoaded(pageLoadedHandler);
Now let’s walk through the implementation of the pageLoadedHandler JavaScript function When the
current client-side PageRequestManager instance invokes this function, it passes two parameters into it
The first parameter references the current client-side PageRequestManager instance and the second
ref-erences the PageLoadedEventArgs object that contains the event data for the pageLoaded event
As Listing 22-12 shows, the pageLoadedHandler method first calls the get_ panelsUpdated
method on the PageLoadedEventArgs object to return a reference to the array that contains all the
UpdatePanel server controls on the current page that were updated during the instantiation/
initialization phase of the current client-side PageRequestManager instance Since this phase occurs
when the current page is accessed for the first time, there are no prior UpdatePanel server controls to
update and therefore the call to the get_panelsUpdated method is bound to return an empty array:
var panelsUpdated = e.get_panelsUpdated();
Next, the pageLoadedHandler method calls the get_panelsCreated method on the
PageLoadedEventArgs object to return a reference to the array that contains all the UpdatePanel
server controls that were created and added to the current page during the instantiation/initialization
phase of the current client-side PageRequestManager instance As I mentioned earlier, because
this phase occurs when the current page is accessed for the first time, all the UpdatePanel server
con-trols on the current page are created and added to the current page, which means that the call into the
get_ panelsCreated method returns an array that contains all the UpdatePanel server controls on
the current page:
var panelsCreated = e.get_panelsCreated();
Trang 31Next, the pageLoadedHandler method instantiates a StringBuilder :
var builder = new Sys.StringBuilder();
Then it populates the StringBuilder with the UniqueID property values of all the UpdatePanel server controls in the panelsUpdated array As I just mentioned, this array is empty:
UpdatePanel server controls on the current page:
for (var j in panelsCreated) {
Trang 32builder.appendLine();
builder.appendLine();
builder.append(“_updatePanelHasChildrenAsTriggers: “);
builder.append(sender._updatePanelHasChildrenAsTriggers);
Next, the pageLoadedHandler method adds the value of the _asyncPostBackTimeout field of the
cur-rent client-side PageRequestManager instance to the StringBuilder Recall that this field contains the
asynchronous page postback request timeout:
PageRequestManager instance to the StringBuilder Recall that the _asyncPostBackControlIDs
field contains the comma-separated list of the UniqueID property values of all the server controls on the
current page that cause asynchronous page postbacks:
builder.appendLine();
builder.appendLine();
builder.append(“_asyncPostBackControlIDs: “);
builder.append(sender._asyncPostBackControlIDs);
Then it adds the content of the _asyncPostBackControlClientIDs field of the current
client-side PageRequestManager instance to the StringBuilder Recall that the
_asyncPostBackControlClientIDs field contains the comma-separated list of the ClientID
property values of all the server controls on the current page that cause asynchronous page postbacks:
builder.appendLine();
builder.appendLine();
builder.append(“_asyncPostBackControlClientIDs: “);
builder.append(sender._asyncPostBackControlClientIDs);
Next, it adds the content of the _postBackControlIDs field of the current client-side
PageRequestManager instance to the StringBuilder Recall that the _postBackControlIDs
field contains the comma-separated list of the UniqueID property values of all the server controls
on the current page that cause synchronous page postbacks:
builder.appendLine();
builder.appendLine();
builder.append(“_postBackControlIDs: “);
builder.append(sender._postBackControlIDs);
Then it adds the content of the _postBackControlClientIDs field of the current client-side
PageRequestManager instance to the StringBuilder Recall that the _postBackControlClientIDs
field contains the comma-separated list of the ClientID property values of all the server controls on the
current page that cause synchronous page postbacks:
builder.appendLine();
builder.appendLine();
builder.append(“_postBackControlClientIDs: “);
Trang 33Finally, the pageLoadedHandler method displays the content of the StringBuilder in a popup, shown in Figure 22-7
alert(builder.toString());
As Figure 22-7 shows:
❑ The panelsUpdated array is empty as expected
❑ The panelsCreated array contains all the UpdatePanel server controls on the current page:
ParentUpdatePanel , StaticChildUpdatePanel , and DynamicChildUpdatePanel , as pected As we discussed, when the current page is loaded for the first time, all the UpdatePanel server controls are created and added to the current page
ex-❑ The _updatePanelIDs field of the current PageRequestManager instance returns the separated list of the UniqueID properties of all the UpdatePanel server controls on the current page: ParentUpdatePanel , StaticChildUpdatePanel , and DynamicChildUpdatePanel Note that the UniqueID property values in this example are the same as the ID property values because none of the UpdatePanel server controls in this example belongs to a parent server control that implements the INamingContainer interface
comma-❑ The _updatePanelClientIDs field of the current PageRequestManager instance returns the comma-separated list of the ClientID properties of all the UpdatePanel server controls
on the current page: ParentUpdatePanel , StaticChildUpdatePanel , and
DynamicChildUpdatePanel Note that the ClientID property values in this example are the same as the ID property values because none of the UpdatePanel server controls in this example belongs to a parent server control that implements the INamingContainer interface
❑ The _updatePanelHasChildrenAsTriggers field of the current PageRequestManger stance returns the comma-separated list of the Boolean values, one for each UpdatePanel server control Because this example contains three UpdatePanel server controls and because the
in-ChildrenAsTriggers properties of all three UpdatePanel server controls are set to true by default, the _updatePanelHasChildrenAsTrigger field contains a comma-separated list of three true values
❑ The _asyncPostBackTimeout field of the current PageRequestManager instance returns the default value, which is 90000
❑ The _asyncPostBackControlIDs field of the current PageRequestManager instance returns the comma-separated list of the UniqueID property values of all asynchronous postback server controls This example contains two asynchronous postback Button server controls:
ParentUpdatePanelTrigger and StaticChildUpdatePanelTrigger
❑ The _asyncPostBackControlClientIDs field of the current PageRequestManager instance returns the comma-separated list of the ClientID property values of all asynchronous postback server controls This example contains two asynchronous postback Button server controls:
ParentUpdatePanelTrigger and StaticChildUpdatePanelTrigger Again, because these two Button server controls do not belong to a server control that implements the
INamingContainer interface, their UniqueID , ClientID , and ID properties have the same values Keep in mind that the arrays returned from the calls into the get_panelsUpdated and
get_panelsCreated methods contain references to the actual updated and created UpdatePanel server controls This gives your event handler (registered for the pageLoaded event of the current
Trang 34PageRequestManager instance) a powerful tool with which to modify the contents of these
UpdatePanel server controls or to enhance their functionality The next example should give you an
idea of the types of things you could do within your event handler
Listing 22-13 contains a page that registers an event handler for the pageLoaded event of the current
PageRequestManager instance, where it attaches a Mover object to each UpdatePanel server control
Recall from Chapter 7 that we developed an ASP.NET AJAX component named Mover When an
instance of this component is attached to a control, the end user can freely move the control
As you can see, the page shown in Listing 22-12 contains two UpdatePanel server controls I’ve
intentionally kept the contents of these UpdatePanel server controls simple so we can focus on what
matters to our discussions However, you can make these contents as complex as you want
Listing 22-13: A Page that Attaches Movers to UpdatePanel Server Controls
var panelsCreated = e.get_panelsCreated();
for (var j in panelsCreated)
{
updatePanelMover = new Delegates.Mover(“container”+j);
updatePanelProvider = new Delegates.UpdatePanelProvider(panelsCreated[j]);
Trang 35<form id=”form1” runat=”server”>
<asp:ScriptManager ID=”ScriptManager1” runat=”server”>
Now let’s walk through the implementation of the pageLoadedHandler JavaScript function
This function invokes the get_panelsCreated method on the PageLoadedEventArgs object to return a reference to the array that contains all the newly created UpdatePanel server control on the current page:
var panelsCreated = e.get_panelsCreated();
Next, the function iterates through the UpdatePanel server controls in the panelsCreated array and takes the following steps for each enumerated UpdatePanel control First it instantiates a Mover object:
updatePanelMover = new Delegates.Mover(“container”+j);
Next, it instantiates an UpdatePanelProvder object, passing in the enumerated UpdatePanel server control as its argument:
updatePanelProvider = new Delegates.UpdatePanelProvider(panelsCreated[j]);
Then it calls the createDelegate static method on the Function to create a delegate that represents the
addUpdatePanel method of the UpdatePanelProvider object:
addUpdatePanelDelegate = Function.createDelegate(updatePanelProvider, updatePanelProvider.addUpdatePanel);
Finally, it invokes the addContent method on the Mover object, passing in the delegate Recall from Chapter 7 that the addContent method automatically invokes this delegate and consequently the
addUpdatePanel method on the UpdataPanelProvider object
updatePanelMover.addContent(addUpdatePanelDelegate);
Trang 36Listing 22-14 presents the content of the Delegates.js JavaScript file The boldfaced portion of this code
listing contains the code for a new ASP.NET AJAX client class named UpdatePanelProvider
Listing 22-14: The Content of the Delegates.js JavaScript File