Solving the ASP.NET UpdateProgress Div Problem

Monday, November 09, 2009 9:58:00 AM Categories: Developer Resources Development mojoPortal Open Source
Rate this Content 2 Votes

 Introduction - What is the ASP.NET UpdateProgress Control?

The UpdateProgress control is a very handy control meant for use in conjunction with an ASP.NET UpdatePanel. The UpdatePanel is an ajax control that makes it very easy to update part of a page using an ajax postback rather than a full postback. This avoids page flicker and also leaves the page not in a postback state, that is, a subsequent refresh of the browser won't force a postback. The UpdateProgress control is desinged to make it easy to show some markup while the update is happening to give the user a visible cue that something is happening. So a typical trick is to show an animated working indicator something like this working indicator

So you would add the UpdateProgress control inside the UpdatePanel something like this:

<asp:Button ID="btnSavePreferences" runat="server" />
<asp:UpdateProgress ID="progress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
<ProgressTemplate>
<img src='<%= Page.ResolveUrl("~/Data/SiteImages/indicators/indicator1.gif") %>' alt=' ' />
</ProgressTemplate>
</asp:UpdateProgress>

The Problem - Block Rendering instead of Inline Rendering

The problem is that the UpdateProgress control renders as a div element which is a block element rather than an inline element, so instead of rendering the indicator right next to your button, it renders it below your button on a new line. In some cases that may be ok, but if you really want the indicator to just be right next to the button it's a problem. I came across this situation recently in my work on mojoPortal and I really wanted to show the indicator in the same line as the button, it gave a bad effect for the indicator to jump below the button. So I did some searching on the internet and found a number of people complaining about this problem and a few less than satisfactory suggestions for solving it.

So, in summary, the problem is that it renders as a div which is a block element and the javascript associated with the control changes from display:none; to display:block when the UpdatePanel is updating.

The Solution- Borrow The UpdateProgress control from the Mono Project and modify it.

What I really wanted was to make the UpdateProgress control render as a span which is an inline element and I wanted the javascript to toggle between display:none; and display:inline;. Often, when I face a situation where an ASP.NET control cannot be coerced into rendering or behaving as I would like, I have found that I can borrow the Mono Project implementation of the ASP.NET control and modify it to meet my needs. Sometimes its more difficult than others to use this approach depending on what mono internals it may be using, but in this case it was fairly easy.

First I grabbed the UpdateProgress.cs from the Mono source code and added it to my project as UpdateProgressSpan.cs and changed the namespace to match my own project. Then it was fairly simple to change the rendering to use a span instead of a div. However, the problem still remained that the javascript would set the display to block which would still make the span render as a block just like a div. So I scrounged around in the javascript for ms ajax and found the relevant part for UpdateProgress. I copied it into my own javascript file, changed the namespace, and modified it to use display:inline instead of display:block.

The only changes I had to make in my UpdateProgressSpan.cs were:

1. In OnPreRender I had to tell it about my javascript like this:

ScriptReference SRef = new ScriptReference();
SRef.Path = "~/ClientScript/ajaxupdateprogressspan.js";
ScriptManager.Scripts.Add(SRef);
ScriptManager.RegisterScriptControl(this);

2. In Render, I changed it to use Span instead of div and use inline instead of block.

3. In the GetScriptDescriptors method I changed it from referencing the original ms ajax to use my custom one like this:

ScriptControlDescriptor descriptor = new ScriptControlDescriptor("mojo._UpdateProgress", this.ClientID);

Finally in my page I used my custom control instead of te ASP.NET version like this:

<asp:Button ID="btnSavePreferences" runat="server" />
<portal:UpdateProgressSpan ID="UpdateProgress2" runat="server" AssociatedUpdatePanelID="UpdatePanel1" >
<ProgressTemplate>
<img src='<%= Page.ResolveUrl("~/Data/SiteImages/indicators/indicator1.gif") %>' alt=' ' />
</ProgressTemplate>
</portal:UpdateProgressSpan>

Problem solved, the working indicator displays right next to the button.

If you would like to use this in your project, feel free, here is a .zip with the files.

Copyright 2003-2010 Joe Audette

Comments

Comments are closed on this post.
Donate Money to support the mojoPortal Project. View Joe Audette's profile on LinkedIn View Joe Audette's profile on The Guild of Accessible Web Designers site