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);