Brothers In Code

...a serious misallocation of .net resources

AsyncPostBackTrigger On A Control External To An Update Panel Doesn't Display An Update Progress Control

Consider the following code:


    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>   
    <div>
      <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
      <asp:Button ID="Button2" runat="server" Text="Button" />
      <asp:Button ID="Button3" runat="server" Text="Button" />
      <asp:UpdatePanel ID="UpdatePanel1" runat="server">
   <Triggers>
     <asp:AsyncPostBackTrigger ControlID="Button2" />
   </Triggers>
      <ContentTemplate>
        <asp:Button ID="Button1" runat="server" Text="Button" />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
      </ContentTemplate>
      </asp:UpdatePanel>
     <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
      <ProgressTemplate>
       Please Wait
      </ProgressTemplate>
     </asp:UpdateProgress>
    </div>


//code behind:
  protected void Page_Load(object sender, EventArgs e)
  {
    Label1.Text = DateTime.Now.ToString();
    Label2.Text = DateTime.Now.ToString();

    if (Page.IsPostBack)
    {
      System.Threading.Thread.Sleep(2000);
    }
  }

In the above example, Button1 will do a partial page update for UpdatePanel1.  Button3 will cause a full postback.  Button two will also do a partial page update for UpdatePanel1 since it is listed as a trigger.  However, Button2 will not cause UpdateProgress1 to be displayed.

There is some help for this on the buttom of an article on codeproject.com, but I needed something for multiple controls.  My solution ended up being two functions:


  private void RegisterExternalTriggerFixForUpdateProgress()
  {
    String updateProgressWTriggerFix = @"
      var triggerMappings = new Array();

      function TriggerMapping(controlId, updatePanelId)
        {
          this.TriggerControlId = controlId;
          this.UpdatePanelId = updatePanelId;
        }
        function RegisterTriggerMapping(controlId, updatePanelId)
        {
          triggerMappings.push(new TriggerMapping(controlId, updatePanelId));
        }
        function GetTriggerMapping(control)
        {
          for(var i=0; i<triggerMappings.length; i++)
          {
            if(triggerMappings[i].TriggerControlId == control.id)
            {
              return triggerMappings[i];
            }
          }
          return null;
        }

        var prm = Sys.WebForms.PageRequestManager.getInstance();
        function CancelAsyncPostBack() {
            if (prm.get_isInAsyncPostBack()) {
              prm.abortPostBack();
            }
        }


        prm.add_initializeRequest(InitializeRequest);
        prm.add_endRequest(EndRequest);
        var postBackElement;
        function InitializeRequest(sender, args) {
            if (prm.get_isInAsyncPostBack()) {
                args.set_cancel(true);
            }
            postBackElement = args.get_postBackElement();
       
            var triggerMapping = GetTriggerMapping(postBackElement);
            if (triggerMapping != null) {
                $get(triggerMapping.UpdatePanelId).style.display = 'block';
            }
        }
        function EndRequest(sender, args) {
            var triggerMapping = GetTriggerMapping(postBackElement);
            if (triggerMapping != null) {
                $get(triggerMapping.UpdatePanelId).style.display = 'none';
            }
        }";

    this.Page.ClientScript.RegisterStartupScript(typeof(Page), "UpdateProgressWTriggerFix", updateProgressWTriggerFix, true);
  }
  protected void RegisterExternalAsyncTrigger(Control triggerControl)
  {
    this.Page.ClientScript.RegisterStartupScript(
      this.GetType(),
      triggerControl.ClientID,
      String.Format(@"RegisterTriggerMapping('{0}','{1}');",
        triggerControl.ClientID,
        UpdateProgress1.ClientID),
      true);
  }

Then to fix a particular AsyncPostBackTrigger control, you just need the following call in your Page_Load:


    //fix for async update from a control outside of the update panel
    RegisterExternalTriggerFixForUpdateProgress();
    RegisterExternalAsyncTrigger(Button2);

Loading