Programming UpdateProgress Controls in Client Script
In this tutorial you will extend the UpdateProgress control with client behavior by writing ECMAScript (JavaScript) code. Your code will use the PageRequestManager class that is part of the Microsoft Ajax Library. In the UpdateProgress control, you will add a button that enables users to cancel an asynchronous postback. As part of this task, you will show or hide the progress message using client script.
This topic assumes that you are familiar with the UpdateProgress control. If not, review the topic Introduction to the UpdateProgress Control.
Prerequisites
To implement the procedures in your own development environment you need:
Microsoft Visual Studio 2005 or Visual Web Developer Express.
An AJAX-enabled ASP.NET Web site.
To cancel an asynchronous postback in client script
Create a new ASP.NET Web page and switch to Design view.
In the AJAX Extensions tab of the toolbox, double-click the ScriptManager control, the UpdatePanel control, and the UpdateProgress controls to add one instance of each of them to the page.
From the Standard tab of the toolbox, add a Label control to the UpdatePanel control, and set the label's Text property to Panel Rendered.
Add a Button control to the UpdatePanel control and set its Text property to Refresh.
In the UpdateProgress control, add the text Processing….
From the HTML tab of the toolbox, add an HtmlButton control to the UpdateProgress control and set its Value attribute to Cancel.
Double-click the Refresh button to add an event handler for its Click event.
Add the following code to the Click handler, which artificially creates a three-second delay and then sets the label to the current server time.
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(3000) Label1.Text = DateTime.Now.ToString() End Sub
protected void Button1_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString(); }
Note
The handler for the Click event intentionally introduces a delay for this tutorial. In practice, you would not introduce a delay. Instead, the delay would be the result of server traffic or of server code that takes a long time to process, such as a long-running database query.
Underneath the <asp:ScriptManager> element, add the following script:
<script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } // --> </script>
<script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } // --> </script>
The script gets the current instance of the PageRequestManager class. It then creates a function that calls the abortPostBack method to stop an asynchronous postback.
Set the onclick attribute of the HtmlButton control to CancelAsyncPostBack, the name of the handler that you created in the previous step.
<input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" />
<input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" />
Add the following style block to the <head> element:
<style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style>
<style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style>
The style settings configure the UpdateProgress control to be displayed at the bottom-left corner of the browser window.
Save your changes, and then press CTRL+F5 view the page in a browser.
Click Refresh.
The progress message appears after a short delay. Allow the partial-page update to finish so that the message in the UpdatePanel control is changed to display the time.
Note
You can configure the time for the delay by setting the DisplayAfter property. The default value is 500 milliseconds.
Click Refresh again and then immediately click Cancel to stop the partial-page update.
Notice that the time in the UpdatePanel is not refreshed.
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(3000) Label1.Text = DateTime.Now.ToString() End Sub </script> <html xmlns="https://www.w3.org/1999/xhtml" > <head runat="server"> <title>UpdateProgress Tutorial</title> <style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"/> <script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } // --> </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Panel rendered."></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="refresh" /> </ContentTemplate> </asp:UpdatePanel> </div> <asp:UpdateProgress ID="UpdateProgress1" runat="server"> <ProgressTemplate> Processing... <input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" /> </ProgressTemplate> </asp:UpdateProgress> </form> </body> </html>
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button1_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString(); } </script> <html xmlns="https://www.w3.org/1999/xhtml" > <head runat="server"> <title>UpdateProgress Tutorial</title> <style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"/> <script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } // --> </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Panel rendered."></asp:Label><br /> <asp:Button ID="Button2" runat="server" OnClick="Button1_Click" Text="refresh" /> </ContentTemplate> </asp:UpdatePanel> </div> <asp:UpdateProgress ID="UpdateProgress1" runat="server"> <ProgressTemplate> Processing... <input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" /> </ProgressTemplate> </asp:UpdateProgress> </form> </body> </html>
Displaying Update Progress Using Client Script
In the following scenarios, the UpdateProgress control will not display automatically:
The UpdateProgress control is associated with a specific update panel, but the asynchronous postback results from a control that is not inside that update panel.
The UpdateProgress control is not associated with any UpdatePanel control, and the asynchronous postback does not result from a control that is not inside an UpdatePanel and is not a trigger. For example, the update is performed in code.
The following procedure shows how to display an UpdateProgress control when the asynchronous postback does not originate inside the associated UpdatePanel control. This procedure assumes that you have completed the first part of this tutorial.
To display an UpdateProgress control programmatically
In the page you created earlier, switch to Design view.
Select the UpdateProgress control, and in the Properties window, set the AssociatedUpdatePanelID property to UpdatePanel1.
Add a Button control anywhere outside the UpdatePanel and UpdateProgress controls.
Set the button's Text property to Trigger and its ID to Panel1Trigger.
Select the UpdatePanel control, and in the Properties window, click the ellipsis (…) in the box for the Triggers property.
The UpdatePanelTrigger Collection Editor dialog box is displayed.
Create an AsyncPostBackTrigger object and set its ControlID property to Panel1Trigger.
Click OK to close the collection editor.
Double click the Trigger button to add an event handler for its Click event.
Add the following code to the Click handler, which artificially creates a three-second delay. It then displays the server time and a message that states that the postback was caused by a trigger.
Protected Sub Panel1Trigger_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(3000) Label1.Text = DateTime.Now.ToString() & " - trigger" End Sub
protected void Panel1Trigger_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString() + " - trigger"; }
In Source view, add the following client script underneath the <script> block already in the page.
prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } }
prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } }
The script does the following:
It defines a handler for the initializeRequest event of the PageRequestManager class. The handler code cancels any asynchronous postbacks that are already in progress. Otherwise, if the postback originates in the Panel1Trigger <div> element, the code displays the UpdateProgress template.
It defines a handler for the endRequest event of the PageRequestManager class. If the postback originates in the Panel1Trigger <div> element, the handler code hides the progress control.
The following example shows the complete script block.
<script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } } // --> </script>
<script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } } // --> </script>
Save your changes, and then press CTRL+F5 to view the page in a browser.
Click the Refresh button.
The progress message appears after a short delay. Allow the partial-page update to finish so that the message in the UpdatePanel control displays the time.
Click the Trigger button.
Notice that the progress message is displayed.
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(3000) Label1.Text = DateTime.Now.ToString() End Sub Protected Sub Panel1Trigger_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(3000) Label1.Text = DateTime.Now.ToString() & " - trigger" End Sub </script> <html xmlns="https://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>UpdateProgress Tutorial</title> <style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } } // --> </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Panel rendered."></asp:Label><br /> <asp:Button ID="Button1" runat="server" Text="refresh" OnClick="Button1_Click" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Panel1Trigger" /> </Triggers> </asp:UpdatePanel> <asp:Button ID="Panel1Trigger" runat="server" Text="Trigger" OnClick="Panel1Trigger_Click" /> <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1"> <ProgressTemplate> Processing... <input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" /> </ProgressTemplate> </asp:UpdateProgress> </div> </form> </body> </html>
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button1_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString(); } protected void Panel1Trigger_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString() + " - trigger"; } </script> <html xmlns="https://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>UpdateProgress Tutorial</title> <style type="text/css"> #UpdatePanel1 { width:200px; height:100px; border: 1px solid gray; } #UpdateProgress1 { width:200px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <script language="javascript" type="text/javascript"> <!-- var prm = Sys.WebForms.PageRequestManager.getInstance(); function CancelAsyncPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); var postBackElement; function InitializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { args.set_cancel(true); } postBackElement = args.get_postBackElement(); if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'block'; } } function EndRequest(sender, args) { if (postBackElement.id == 'Panel1Trigger') { $get('UpdateProgress1').style.display = 'none'; } } // --> </script> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Panel rendered."></asp:Label><br /> <asp:Button ID="Button1" runat="server" Text="refresh" OnClick="Button1_Click" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Panel1Trigger" /> </Triggers> </asp:UpdatePanel> <asp:Button ID="Panel1Trigger" runat="server" Text="Trigger" OnClick="Panel1Trigger_Click" /> <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1"> <ProgressTemplate> Processing... <input id="Button2" type="button" value="cancel" onclick="CancelAsyncPostBack()" /> </ProgressTemplate> </asp:UpdateProgress> </div> </form> </body> </html>
Review
This tutorial showed ways you can extend the behavior of the UpdateProgress control by writing JavaScript code. You can use events and methods of the PageRequestManager class to cancel an asynchronous postback and to show and hide an UpdateProgress control programmatically.
See Also
Reference
Sys.WebForms.PageRequestManager Class