Ajax.Net Example: Using an UpdatePanelAnimationExtender to place an animated gif over a GridView

 I recently was working on an Asp.Net project that contained quite a few search pages.  These pages all followed a similar structured pattern where the user had a set of fields they could filter on by typing in values and pressing the search button.  The results were displayed in a GridView where the user could sort by clicking on column headers, export the results to excel, etc...  To help improve user experience, we placed each of the GridViews in an asp UpdatePanel so while the user refined the search (sorting, adding or removing additional filters), only the GridView would be refreshed and not the entire page.  Additionally, we wanted to add a few standard UI cues (disabling the Search button, fading out the GridView, and placing a progress indicator over the GridView) letting the user know an operation was currently in progress.

Download Code | View live demo

kick it on DotNetKicks.com

It turned out that adding these UI cues was pretty easy with the help of the UpdatePanelAnimationExtender.  Applying the first 2 cues (disabling the Search button and fading out the GridView) were really simple since there were already a couple of Animation Actions already defined specifically for these tasks.  Placing the animated gif in the center of the GridView was only slightly more difficult.  After the wrapping the GridView inside the UpdatePanel and defining the Search button as the trigger, I added the markup for the UpdateProgressAnimationExtender, specify which animations I would like and when they should run.  As you can see in the code snippet below, I am telling the extender control to run the ScriptAction, EnableAction and FadeOut actions both OnUpdating (when the panel starts the async-postback) and OnUpdated (when the panel has been refreshed).  When OnUpdating runs, the onUpdating javascript function is invoked centering the animated gif over the GridView, the btnSearch asp:Button is disabled, and the contents of the UpdatePanel are faded-out.  OnUpdated fires the animations that are responsible for reversing these actions - the btnSearch button is re-enabled, the UpdatePanel is faded back in, and the onUpdated javascript function is invoked removing the animated gif.         

<asp:UpdatePanel ID="updatePanel" runat="server">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="btnSearch" EventName="Click" />
    </Triggers>
    <ContentTemplate>
        <asp:GridView ID="gvCustomers" runat="server" AllowPaging="true" AllowSorting="true"
            PageSize="20" DataSourceID="sqldsCustomers" Width="95%">
            <AlternatingRowStyle BackColor="aliceBlue" />
            <HeaderStyle HorizontalAlign="Left" />
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>
<ajaxToolkit:UpdatePanelAnimationExtender ID="upae" BehaviorID="animation" runat="server" TargetControlID="updatePanel">
    <Animations>
        <OnUpdating>
            <Parallel duration="0">
                <%-- place the update progress div over the gridview control --%>
                <ScriptAction Script="onUpdating();" />  
                <%-- disable the search button --%>                       
                <EnableAction AnimationTarget="btnSearch" Enabled="false" />
                <%-- fade-out the GridView --%>
                <FadeOut minimumOpacity=".5" />
             </Parallel>
        </OnUpdating>
        <OnUpdated>
            <Parallel duration="0">
                <%-- fade back in the GridView --%>
                <FadeIn minimumOpacity=".5" />
                <%-- re-enable the search button --%>  
                <EnableAction AnimationTarget="btnSearch" Enabled="true" />
                <%--find the update progress div and place it over the gridview control--%>
                <ScriptAction Script="onUpdated();" /> 
            </Parallel> 
        </OnUpdated>
    </Animations>
</ajaxToolkit:UpdatePanelAnimationExtender>
<div id="updateProgressDiv" style="display: none; height: 40px; width: 40px">
    <img src="Img/dot-net-green.gif" />
</div>

Like I mentioned earlier, centering the animated gif was only slightly more work.  To accomplish this I included a fixed width div tag containing the image and set its display style to none.  Then when the OnUpdating animation fires the ScriptAction, I find the div, set the display back to visible, figure out the bounds of both the GridView and the progress div, and finally I do the math to determine when the div needs to be placed to overlay the GridView.  The onUpdated function just sets the display style of the div back to none.  Here are the functions ...

function onUpdating(){
    // get the update progress div
    var updateProgressDiv = $get('updateProgressDiv'); 
    // make it visible
    updateProgressDiv.style.display = '';

    //  get the gridview element        
    var gridView = $get('<%= this.gvCustomers.ClientID %>');
    
    // get the bounds of both the gridview and the progress div
    var gridViewBounds = Sys.UI.DomElement.getBounds(gridView);
    var updateProgressDivBounds = Sys.UI.DomElement.getBounds(updateProgressDiv);
    
    //    do the math to figure out where to position the element (the center of the gridview)
    var x = gridViewBounds.x + Math.round(gridViewBounds.width / 2) - Math.round(updateProgressDivBounds.width / 2);
    var y = gridViewBounds.y + Math.round(gridViewBounds.height / 2) - Math.round(updateProgressDivBounds.height / 2);
    
    //    set the progress element to this position
    Sys.UI.DomElement.setLocation (updateProgressDiv, x, y);        
}

function onUpdated() {
    // get the update progress div
    var updateProgressDiv = $get('updateProgressDiv'); 
    // make it invisible
    updateProgressDiv.style.display = 'none';
}

 

Here is the complete markup for the page ...

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

<!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>Untitled Page</title>
    <script type="text/javascript" language="javascript">
    
    function onUpdating(){
        // get the update progress div
        var updateProgressDiv = $get('updateProgressDiv'); 
        // make it visible
        updateProgressDiv.style.display = '';

        //  get the gridview element        
        var gridView = $get('<%= this.gvCustomers.ClientID %>');
        
        // get the bounds of both the gridview and the progress div
        var gridViewBounds = Sys.UI.DomElement.getBounds(gridView);
        var updateProgressDivBounds = Sys.UI.DomElement.getBounds(updateProgressDiv);
        
        //    do the math to figure out where to position the element (the center of the gridview)
        var x = gridViewBounds.x + Math.round(gridViewBounds.width / 2) - Math.round(updateProgressDivBounds.width / 2);
        var y = gridViewBounds.y + Math.round(gridViewBounds.height / 2) - Math.round(updateProgressDivBounds.height / 2);
        
        //    set the progress element to this position
        Sys.UI.DomElement.setLocation (updateProgressDiv, x, y);        
    }

    function onUpdated() {
        // get the update progress div
        var updateProgressDiv = $get('updateProgressDiv'); 
        // make it invisible
        updateProgressDiv.style.display = 'none';
    }
    
    </script>

</head>
<body>
    <form id="form" runat="server">
        <asp:ScriptManager ID="scriptManager" runat="server" />
        <div>
            <asp:SqlDataSource ID="sqldsCustomers" runat="server" 
                SelectCommand="select customerid, companyname, contactname, contacttitle from dbo.customers"
                SelectCommandType="Text" ConnectionString="server=mberseth;database=northwind;Trusted_Connection=yes;" />
            
            <p>
                Example of using an UpdatePanelAnimationExtender to place an animated gif over a GridView while the 
                GridView is being refreshed.
            </p>
            <br />
            <table border="0" width="95%">
                <tr>
                    <td align="center">Customer ID</td>
                    <td align="right"><asp:TextBox ID="txtCustomerID" runat="server" /></td>
                    <td align="center">Company Name</td>
                    <td align="right"><asp:TextBox ID="txtCompanyName" runat="server" /></td>
                    <td align="center">Contact Name</td>
                    <td align="right"><asp:TextBox ID="txtContactName" runat="server" /></td>
                </tr>                                
                <tr>
                    <td colspan="6" align="right"><asp:Button ID="btnSearch" runat="server" Width="75" Text="Search" OnClick="BtnSearch_Click" /></td>
                </tr>
            </table>
            <br />
            
            <asp:Label ID="lblTitle" runat="server" Text="Customers" BackColor="lightblue" Width="95%" />
            <asp:UpdatePanel ID="updatePanel" runat="server">
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="btnSearch" EventName="Click" />
                </Triggers>
                <ContentTemplate>
                    <asp:GridView ID="gvCustomers" runat="server" AllowPaging="true" AllowSorting="true"
                        PageSize="20" DataSourceID="sqldsCustomers" Width="95%">
                        <AlternatingRowStyle BackColor="aliceBlue" />
                        <HeaderStyle HorizontalAlign="Left" />
                    </asp:GridView>
                </ContentTemplate>
            </asp:UpdatePanel>
            <ajaxToolkit:UpdatePanelAnimationExtender ID="upae" BehaviorID="animation" runat="server" TargetControlID="updatePanel">
                <Animations>
                    <OnUpdating>
                        <Parallel duration="0">
                            <%-- place the update progress div over the gridview control --%>
                            <ScriptAction Script="onUpdating();" />  
                            <%-- disable the search button --%>                       
                            <EnableAction AnimationTarget="btnSearch" Enabled="false" />
                            <%-- fade-out the GridView --%>
                            <FadeOut minimumOpacity=".5" />
                         </Parallel>
                    </OnUpdating>
                    <OnUpdated>
                        <Parallel duration="0">
                            <%-- fade back in the GridView --%>
                            <FadeIn minimumOpacity=".5" />
                            <%-- re-enable the search button --%>  
                            <EnableAction AnimationTarget="btnSearch" Enabled="true" />
                            <%--find the update progress div and place it over the gridview control--%>
                            <ScriptAction Script="onUpdated();" /> 
                        </Parallel> 
                    </OnUpdated>
                </Animations>
            </ajaxToolkit:UpdatePanelAnimationExtender>
            <div id="updateProgressDiv" style="display: none; height: 40px; width: 40px">
                <img src="Img/dot-net-green.gif" />
            </div>
        </div>
    </form>
</body>
</html>

TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/23

Listed below are links to weblogs that reference Ajax.Net Example: Using an UpdatePanelAnimationExtender to place an animated gif over a GridView:

» AJAX loading indicator like GMail from Community Blogs
Simone Chiaretta wrote a very nice post about building a Gmail-like loading indicator (that means top [Read More]

» [Reference]Ajax.Net Example: Using an UpdatePanelAnimationExtender to place an animated gif over a GridView from JerryZhao
Ajax.Net Example: Using an UpdatePanelAnimationExtender to place an animated gif over a GridView [Read More]

Comments


Posted by: gokhan on June 4, 2007 06:16 AM

very useful article..thankss..

Matt,

Very interesting demos that you have on your site. Thanks for taking the time to put them up.
I have taken your code and applied it to an page of mine, but I am having some issues with Mozilla. It works fine in IE and your Grid Example works fine in both.

For some reason with mine, it fades properly in Mozilla, but when the panel is updated it does not fade back in, it actually fades out even lighter and stays that way. When it updates again, it fades darker and then when done fades back to the almost transparent state.

Differences from your example:
Using this with MasterPages,
Using Virtual Earth on the page, but not in the update panel.

I was wondering if you have run into this issue at all in your development. Thank you for your time.

Christian

Posted by: Alexander on July 2, 2007 02:07 PM

Very cool! Very useful! Great work!

Thank you! I owe you a beer/drink/pat on the shoulder.


Bye
Alexander

Posted by: abdelmasseh on July 6, 2007 04:47 PM

thank you

Posted by: alborz on July 30, 2007 10:49 AM

Hi matt,
Your demo is very usefull.
I have a problem with my program. i have to updatePanel and two UpdatePanelAnimationExtender in the same page. but both of them executed when one of the update pannels is callbacked.
may you help me. thank's

Posted by: Mike on August 9, 2007 01:13 PM

Hi, nice demo, except I'm having some problems with IE7, as well as the javascript code.

In IE7, after the UpdatePanel is refreshed, sometimes the gridview ends up being cut off, as if it cannot wrap some of the text, or dynamically resize itself. This only happens when I use the animation extender.

Another problem is that the javascript code to place the gif over the gridview doesn't seem to find the gridview properly (it's always null) and therefore the gif is always at the bottom.

Any help would be appreciated.
Thanks

Posted by: Becky on August 17, 2007 01:35 PM

Hi Matt,
Great article! My grid is fading properly, the button is disabled properly...however my image is always at the bottom of the page. Is there a way I can just have it at the top left of the update panel?

Thanks!

Posted by: Toast on August 23, 2007 10:14 AM

Hi Matt,

works great, but for some reason, I can't see my image. I'm wondering about the line:

I've added an alert to the onUpdating function and this doesn't appear. I've got AjaxControlToolkit v1.0.10123.0...

Thanks

Toast

Posted by: Chris on September 27, 2007 01:00 AM

Matt,

Cool demo. I'm having problems with the animation extender in ie7. While fading the grid nack in, the contents of the grid are cut off.

Any help would be greatly appreciated.

TIA,
Chris

@Chris

Thanks for the feedback Chris. Would you mind posting the code in a comment or sending it to me at matt@mattberseth.com?

Thanks,
Matt

Posted by: Erik on October 23, 2007 04:11 PM

Hi Matt -
I have the same problem with the content in the gridview being cutoff, if the updatepanel RenderMode is set to inline. If the RenderMode is set to block, then the columns are squished together. This only happens when there is a UpdatePanelAnimationExtender on the page as well.

If you found the solution to chris's problem, could you please post back here?

Thanks!

Posted by: amir on February 1, 2008 08:45 AM

thank you thank you thank you

Posted by: Andrew Wait on February 7, 2008 11:06 AM

Nice example.. but I have question about the styles on the page...

Using IE7 the style of the text on page 1 is different to all subsequent pages.. it seems that the page LOOSES the style as set once the updatepanel comes into play and reverts to the browser default (at least with IE7) ... am I mad? Any comments/workarounds?

Matt,

Great article! Thanks for sharing... exactly what I was looking for today!

Posted by: Kapil Saraswat on April 13, 2008 09:24 AM

Hi Matt,
Its really a great article and it helps me in acheving my goals.

Thanks once again.

Posted by: Fenil Desai on April 30, 2008 05:56 AM

I m using a Master Page & in the Content PAge there is a grid view.
while using var gridView = $get('');
I m not getting the grid view element.

Pls help.

Posted by: Giorgio Bozio on May 25, 2008 11:09 AM

Hi!
Great post!
If you don't want to show the gif if the grid is empty (no rows) you can modify the javascript function onUpdating() to show the div only if the grid is visible, just like this:

function onUpdating(){

// get the update progress div
var updateProgressDiv = $get('updateProgressDiv');
// get the gridview element
var gridView = $get('');
var v = Sys.UI.DomElement.getVisibilityMode(gridView);

if (v)
{
// make it visible
updateProgressDiv.style.display = '';

// get the bounds of both the gridview and the progress div
var gridViewBounds = Sys.UI.DomElement.getBounds(gridView);
var updateProgressDivBounds = Sys.UI.DomElement.getBounds(updateProgressDiv);

// do the math to figure out where to position the element (the center of the gridview)
var x = gridViewBounds.x + Math.round(gridViewBounds.width / 2) - Math.round(updateProgressDivBounds.width / 2);
var y = gridViewBounds.y + Math.round(gridViewBounds.height / 2) - Math.round(updateProgressDivBounds.height / 2);

// set the progress element to this position
Sys.UI.DomElement.setLocation (updateProgressDiv, x, y);
}
}

Posted by: Ivan Draga on June 18, 2008 07:52 AM

Animation and loading data in example at all are not bound between itself, try more data and see.
Unholy english? May be.

Posted by: marcus on July 9, 2008 09:29 AM

I m using a Master Page & the Content Page had a grid view.
var gridView = $get(''); is returning me NULL

Pls help.

Posted by: Ed on July 17, 2008 07:42 PM

I found a bug with the UpdatePanelAnimationExtender and I was curious if anyone else has seen this issue.

I am setting the focus of a textbox when the page loads. Everything worked fine until I added the UpdatePanelAnimationExtender to the page. I implemented it the same way as this awesome example and the functionality of the animation works great it just seems to lose focus of the textbox.

Any ideas as to why this is happening?

P.S. Matt, your blog rules. Every .net blog should be in your format(post, live demo)! You da mon!

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Sponsor

Recent Comments

  • Ed wrote: I found a bug with the UpdatePanelAnimationExtender and I was curious if anyone else has seen this i...
  • marcus wrote: I m using a Master Page & the Content Page had a grid view. var gridView = $get(''); is returning me...
  • Ivan Draga wrote: Animation and loading data in example at all are not bound between itself, try more data and see. Un...
  • Giorgio Bozio wrote: Hi! Great post! If you don't want to show the gif if the grid is empty (no rows) you can modify the ...
  • Fenil Desai wrote: I m using a Master Page & in the Content PAge there is a grid view. while using var gridView = $get(...
  • Kapil Saraswat wrote: Hi Matt, Its really a great article and it helps me in acheving my goals. Thanks once agai...
  • Kindler Chase wrote: Matt, Great article! Thanks for sharing... exactly what I was looking for today!...
  • Andrew Wait wrote: Nice example.. but I have question about the styles on the page... Using IE7 the style of the tex...

Sponsor