UpdateProgress Control

UpdateProgress Control

As asynchronous updates are happening, you may want to let the user know that there is work pending. Otherwise, any time the response is not instantaneous, the user will be left wondering if their action has been ignored. With no visual acknowledgement of the input that is causing asynchronous work, the experience can be worse than the screen going blank waiting for a response from a full postback. Therefore, Microsoft created the UpdateProgress control to make it easy to provide visual feedback to the user to indicate that the update is being processed. This is something like a “busy” hourglass cursor in Windows applications, but this does not involve changing the cursor.

Listing 2-4 (UpdateProgress.aspx.cs) is a code-behind file that again updates the rendering with the current time on the server. To make it appear as though the page is doing some heavy lifting that the user might need to wait for, I have added a Sleep method call so that the content is not returned instantly. Sleep simulates a short time lag that may result from a query to a database, or any other server-side processing.

Listing 2-4
Image from book

using System;
using System.Web.UI;

public partial class UpdateProgress : System.Web.UI.Page
{
    protected override void  OnLoad(EventArgs e) {
        System.Threading.Thread.Sleep(4000);
        base.OnLoad(e);
        string theTime = DateTime.Now.ToLongTimeString();

        for(int i = 0; i < 3; i++) {
            theTime += "<br />" + theTime;
        }
        time1.Text = theTime;
    }
}
Image from book

The page markup has an UpdatePanel where the time1 label is and will be updated. It is shown in Listing 2-5 (UpdateProgress.aspx). Besides the UpdatePanel, there is the addition of an UpdateProgress control that will be displayed while the asynchronous postback is underway.

Listing 2-5
Image from book
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="UpdateProgress.aspx.cs" 
Inherits="UpdateProgress" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Update Progress</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

some page content<br />
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DynamicLayout="true" 
AssociatedUpdatePanelID="UpdatePanel1" >
<ProgressTemplate>
<img src=progress.gif />
</ProgressTemplate>
</asp:UpdateProgress>
more page content<br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <div style="border-style:solid;background-color:gray;">
        <asp:Button ID="Button1" runat="server" Text="Update" /><br /><br />
        <asp:Label runat="server" ID="time1"></asp:Label><br />
        </div><br />
    </ContentTemplate>
</asp:UpdatePanel><br />
</div>
</form>
</body>
</html> 
Image from book

Like the UpdatePanel control, the UpdateProgress control has a template that holds the content that it will display. In this example, the ProgressTemplate contains two image tags. Initially, the progress.gif images are not visible. But while the request is pending they are displayed between the top two lines of text, as shown in Figure 2-5.

Image from book
Figure 2-5

I just used the default values for the UpdateProgress control, which results in a 500-millisecond delay before the ProgressTemplate is shown. If it were to be displayed instantly with data returned quickly, the result would have been unacceptable flicker and flash that the UpdatePanel was supposed to avoid in the first place. To avoid this flicker in the event of a quick data fetch, you can configure the UpdateProgress control using the DisplayAfter property, which takes an argument to indicate how long it should delay in milliseconds. If an asynchronous update takes longer than the DisplayAfter threshold, the contents of the UpdateProgress are displayed:

<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter=800 >

You are probably less likely to change the DisplayAfter default than the value of DynamicLayout. The default behavior is not to allocate any space for the contents of the UpdateProgress. Figure 2-6 shows the page when no update is being made. Notice that no space is provided for the progress.gif images seen in Figure 2-5. Instead, room is made for them only when needed. As illustrated in Figure 2-5, the rest of the page was shifted down slightly to make room for the images. This can be disconcerting to users to see the page layout change for a short time. To preallocate the space and avoid a change in the layout, set DynamicLayout to false:

<asp:UpdateProgress ID="UpdateProgress1" runat="server" DynamicLayout="false"  >
Image from book
Figure 2-6

The layout options will really depend on the nature of your application. The UpdateProgress will display for every asynchronous postback unless you assign it specifically to a single UpdatePanel using the AssociatedUpdatePanelID property:

<asp:UpdateProgress ID="UpdateProgress1" runat="server"
AssociatedUpdatePanelID="UpdatePanel1" >

One common approach is to use a CSS class with the UpdateProgress that controls its positioning so that the ProgressTemplate contents are displayed as a layer right over the top of the UpdatePanel being affected. The following is an example set of styles that, when associated with a div for an UpdateProgress will produce a small square on the screen to contain whatever images or other information you want to display while an update is occurring.

<style type="text/css">
.progress 
{
    border:solid;
    background-color: white;
    position: absolute; 
    top: 180px; 
    left: 180px; 
    width: 60px; 
    height: 60px; 
    padding-left:40px; 
    padding-top:40px;
    z-index:1
}
</style>