Introduction
ASP.NET AJAX has a cool UpdateProgress
control that provides a visual indicator while one or more of the UpdatePanel
controls are being updated. However, it will be much more useful if all other elements on the page could be disabled when the UpdateProgress
is shown. This led me to build the ModalUpdateProgress
control in which the UpdateProgress
will act as a modal popup.
How UpdateProgress Control Works
If you open up System.Web.Extensions.dll using reflector, you will be able to look up how UpdateProgress control works. Simply put, it implements IScriptControl
's two methods GetScriptDescriptors()
and GetScriptReferences()
. According to the AJAX documentation, GetScriptDescriptors()
returns a list of components, behaviors, and client controls required for the UpdateProgress
control's client functionality; and GetScriptReferences()
returns a list of client script library dependencies for the UpdateProgress
control. In GetScriptDescriptors()
, the UpdateProgress
control registers a ScriptControlDescriptor
with type name Sys.UI._UpdateProgress
, which is a class available in MicrosoftAjaxWebForms.js (MicrosoftAjaxWebForms.js is one of the ASP.NET AJAX client script libraries, embedded in the System.Web.Extensions.dll). It is pretty straightforward to understand the logic in Sys.UI._UpdateProgress
by looking into the debug version of MicrosoftAjaxWebForms.js.
Building the ModalUpdateProgress Control
First, we derive ModalUpdateProgress
from UpdateProgress
so that we can reuse its existing properties and interface. Then we need to override the two methods GetScriptDescriptors()
and GetScriptReferences()
, and implement the client-side script component. We will name the client script component as Sys.UI._ModalUpdateProgress
, which in turn will be a sub class of Sys.UI._UpdateProgress
.
The following is the detail implementation of GetScriptDescriptors()
and GetScriptReferences():
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
if (((this.Page != null) && this.ScriptManager
.SupportsPartialRendering) && this.Visible)
{
ScriptControlDescriptor desc = new ScriptControlDescriptor(
"Sys.UI._ModalUpdateProgress", this.ClientID);
string updatePanelClientID = null;
if (!string.IsNullOrEmpty(this.AssociatedUpdatePanelID))
{
UpdatePanel panel = this.NamingContainer.FindControl(this
.AssociatedUpdatePanelID) as UpdatePanel;
if (panel == null)
{
panel = this.Page.FindControl(this
.AssociatedUpdatePanelID) as UpdatePanel;
}
if (panel == null)
{
throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture, "No UpdatePanel
found for AssociatedUpdatePanelID '{0}'.",
new object[] { this.AssociatedUpdatePanelID }));
}
updatePanelClientID = panel.ClientID;
}
string backgroundCssClass = null;
string cancelControlID = null;
if (!string.IsNullOrEmpty(this._backgroundCssClass))
{
backgroundCssClass = this._backgroundCssClass;
}
if (!string.IsNullOrEmpty(this._cancelControlID))
{
cancelControlID = this._cancelControlID;
}
desc.AddProperty("associatedUpdatePanelId", updatePanelClientID);
desc.AddProperty("dynamicLayout", this.DynamicLayout);
desc.AddProperty("displayAfter", this.DisplayAfter);
desc.AddProperty("backgroundCssClass", backgroundCssClass);
desc.AddProperty("cancelControlID", cancelControlID);
yield return desc;
}
}
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
yield return new ScriptReference("AjaxControls.ModalUpdateProgress.js", "
AjaxControls");
}
Both methods return IEnumerable
's that will be later handled by ScriptManager
.
To implement the client-side script component Sys.UI._ModalUpdateProgress
, we can borrow scripts from the ModalPopup
control available in the AJAX Control Toolkit. In order to get the script to work for the control, I have to make some minor tweakings, which won't be discussed here. For those who are interested, please look into the ModalUpdateProgress.js in the source for detailed implementation.
How to Use
Just like the UpdateProgress
control, you can use the ProgressTemplate
property to customize your progress indicator in ModalUpdateProgress
.
The ModalUpdateProgress
control has an extra property BackgroundCssClass
which is used to set the CSS class for the background when the control is displayed. In addition, the ProgressTemplate can include a button that the user can click on to cancel the update in progress. In order for the cancel button to work, you should specify the CancelControlID
property using the button ID in the ProgressTemplate
.
The following shows an example of adding the ModalUpdateProgress
to the page:
<asp:ModalUpdateProgress ID="ModalUpdateProgress1" DisplayAfter="0"
runat="server" BackgroundCssClass="modalBackground">
<ProgressTemplate>
<div class="modalPopup">
Loading <img src="indicator.gif" align="middle" />
</div>
</ProgressTemplate>
</asp:ModalUpdateProgress>
To see how it works, please check out the demo website I have included in the download. The ModalUpdateProgress
control supports all the features that UpdateProgress
has, including associating the ModalUpdateProgress
with an UpdatePanel
.
The control passed testing under IE6/7 and Firefox 2.0. Please leave your comments here if you find any problems.