0

I'm fairly new to webdevelopment and I can't seem to get a loading gif to appear, while I am executing a code behind export.

My onclick event is on an Imagebutton inside a gridview. Can you please help me? Here I have the ImageButtons:

<HeaderTemplate>
      <asp:ImageButton ID="btnExport"  OnClick="btnExport_Click" runat="server" ImageUrl="~/Images/excel.gif"  AlternateText="Export top records!"/>
      <asp:ImageButton ID="btnExportRed"   OnClick="btnExportRed_Click" runat="server" ImageUrl="~/Images/excel_red.gif"  AlternateText="Export all records!"/>
 </HeaderTemplate>

this is my code behind:

protected void btnExport_Click(object sender, EventArgs e)
 {
    try
    {
        LoadWaitImage();


          [functional code]

      UnloadWaitImage();
    }
    catch (Exception ex)
    {
        lblMessage.Text = ex.Message;
        upnlMsg.Update();
       UnloadWaitImage();
    }
}


private void LoadWaitImage()
 {
    ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "showMyImage", "hideLoading()", true);
 }

private void UnloadWaitImage()
{
    ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "showMyImage", "hideLoading()", true);
}

and the js to fire:

function showLoading() 
{
   document.getElementById('lblMessage').value = "";
   document.getElementById('ucMarketing_btnSearch').disabled = true;
   document.getElementById('btnClearFilters').disabled = true;
   document.getElementById('imgSaveToSegments').disabled = true;
   document.getElementById('divLoadingImg2').style.display = "";
 }
function hideLoading()
{
  document.getElementById('ucMarketing_btnSearch').disabled = false;
  document.getElementById('btnClearFilters').disabled = false;
  document.getElementById('imgSaveToSegments').disabled = false;
  document.getElementById('divLoadingImg2').style.display = "none";
 }
Ana Demeny
  • 31
  • 1
  • 4
  • `LoadWaitImage` is calling `hideLoading()`, is that a typo? – Graham Clark Aug 29 '12 at 08:18
  • yes, it is: private void LoadWaitImage() { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "showMyImage", "showLoading()", true); } private void UnloadWaitImage() { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "hideMyImage", "hideLoading()", true); } – Ana Demeny Aug 29 '12 at 08:20
  • also, here is the div containing the image: It is outside the GridView but in the same UpdatePanel – Ana Demeny Aug 29 '12 at 08:21
  • it's quite hard to read code in the comments, you'd be better off editing your question and putting it in there. – Graham Clark Aug 29 '12 at 08:28

2 Answers2

0

I don't think your current idea is going to work. The client browser that's rendering your HTML is completely separate from the server running your code-behind. When an ImageButton is clicked, the browser synchronously posts your HTML form to the server, and waits for a response. This response will be sent some time after the end of your event handler method.

If you want to do stuff on the client side (like showing and hiding an image), you're going to need to do things asynchronously, using AJAX. ASP.Net WebForms makes this very easy with the UpdatePanel control.

To get this working, you would surround the area of the page you want to change with an UpdatePanel control. Then add one or more triggers that you want to cause the update. And finally use the UpdateProgress control to show your loading image. Something like this:

<asp:GridView runat="server">
   ...
   <HeaderTemplate>
      <asp:ImageButton ID="btnExport" OnClick="btnExport_Click" runat="server" 
            ImageUrl="~/Images/excel.gif"  AlternateText="Export top records!"/>
      <asp:ImageButton ID="btnExportRed" OnClick="btnExportRed_Click" runat="server"
            ImageUrl="~/Images/excel_red.gif"  AlternateText="Export all records!"/>
   </HeaderTemplate>
</asp:GridView>

<asp:UpdatePanel ID="Update" runat="server">
   <asp:UpdateProgress ID="Progress" runat="server">
      <ProgressTemplate>
         <!-- HTML/ASP for your image -->
      </ProgressTemplate>
   </asp:UpdateProgress>
   <Triggers>
      <asp:AsyncPostBackTrigger ControlID="btnExport" EventName="Click" />
   </Triggers>
</asp:UpdatePanel>

If you want to do more client-side things, have see this answer.

Community
  • 1
  • 1
Graham Clark
  • 12,886
  • 8
  • 50
  • 82
  • Thank you very much for your help. I tried wrapping my buttons in an UpdatePanel, but it seems that AsyncPostBack doesn't like Response.BinaryWrite. As I was doing an export, I couldn't get rid of that. – Ana Demeny Aug 31 '12 at 07:54
  • ah ok, I didn't realise that's what you were doing. I guess you would need some client-side code (e.g. a jQuery click event handler) to show a loading image before the request is sent to the server. However I'm not sure if the animation would continue in this case. – Graham Clark Aug 31 '12 at 08:23
  • yes, that's exactly how I solved the problem. See my answer :). Thanks again very much – Ana Demeny Aug 31 '12 at 08:37
0

In the end, I used an OnClientClick event to start my Js. The OnClick event, executes my server side function for the export. In my export function I added a unique cookie token. I store that token in a hidden field, and change it every second. In the Js function I start timer and check for the cookie to match the token. If it does, I hide my loading image.

I found this solution here: Detect when browser receives file download.

Here's an example: http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx.

Community
  • 1
  • 1
Ana Demeny
  • 31
  • 1
  • 4