In-Depth: The UpdatePanel ASP.NET AJAX Server Control: Triggers and UpdateMode
By using asynchronous post-backs with the new ASP.NET AJAX UpdatePanel server control, you have the unique opportunity to improve both performance and user experience of your web pages.
[Update: 7/31/2007] Per request I have included the code for the live demo for download
Performance gains are achieved because ...
- Less data is round-tripped during an asynchronous post-back - keeping the network load light
- The browser does not have to rerender the complete page, just the part that was updated
- The server does not need to generate the full page output, just the portion(s) that are updated
User experience is improved because ...
- Responsiveness is increased as the user can continue to interact with the page while the asynchronous operation is executing
- The complete page is not always reloading
If you are not familiar with AJAX, or if you are familiar but need a refresher, here is a live demo page. The page contains two GridViews, the top one does not use AJAX so when you click a column header to sort the grid or try paging through the records, the complete page will reload so the GridView can be updated. The second grid contains the same data except it is AJAX enabled. With this grid, clicking the column headers or paging buttons causes the bottom grid top be rerendered without having the complete page refresh.
Luckily, incorporating AJAX into existing ASP.NET pages is fairly simple. You wrap the contents you want updated inside an UpdatePanel and define what server control 'triggers' the panel to refresh. Where is gets a little more tricky is understanding how to specify exactly what actions causes the panel to update. The panels UpdateMode and ChildrenAsTriggers properties as well as any defined triggers determine this behavior. The rest of this post discusses these items in more detail.
Triggers
The ASP.NET AJAX framework defines two types of triggers: asynchronous post-back triggers and post-back triggers. They can be created declaratively when defining the markup for the UpdatePanel or programmatically via the ScriptManager object (use RegisterPostBackControl for registering a post-back trigger and RegisterAsyncPostBackControl for an asynchronous post-back trigger). Both of these trigger types are useful, but in different ways.
Asynchronous Post-Back Triggers
An asynchronous post-back trigger is used to update the contents of an UpdatePanel when an event is fired on the designated server control.
Asynchronous post-back triggers are useful for ...
- Identifying a specific control outside of the UpdatePanel that causes an aync post-back
- Identifying a specific control that is contained within the UpdatePanel that causes an async post-back (This would only be useful when the ChildrenAsTriggers property is set to false)
- Identifying a specific control inside a nested UpdatePanel that causes an async post-back
The following live demo displays an order look-up screen that accepts an order id as input and refreshes the GridView with the line items for the order. The Button btnFindOrder is declaratively marked as an asynchronous trigger for the panel, so anytime the click event is triggered the panel is refreshed. Here is the markup for this portion of the page:
<asp:UpdatePanel ID="updatePanel" runat="server"> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnFindOrder" EventName="Click" /> </Triggers> <ContentTemplate> <asp:Label runat="server" Text="Orders" BackColor="lightblue" Width="95%" /> <asp:GridView id="gvOrderDetails" runat="server" DataSourceID="sqldsOrderDetails" AllowSorting="true" Width="95%" > <AlternatingRowStyle BackColor="aliceBlue" /> <HeaderStyle HorizontalAlign="Left" /> </asp:GridView> </ContentTemplate> </asp:UpdatePanel>
A similar result can be achieved by programmatically calling the RegisterAsyncPostBackControl of the ScriptManager object. Because the ASP.NET AJAX framework does not maintain controls registered as asynchronous post-back controls between post-backs, we will need to register this unconditionally in the Page_Load handler:
protected void Page_Load(object sender, EventArgs e) { this.scriptManager.RegisterAsyncPostBackControl(this.btnFindOrder); }
With the corresponding markup on the page. The only difference from the previous example is the AsynchronousPostBackTrigger has been removed from the markup and is now added programmatically.
<asp:TextBox ID="txtOrderID" runat="server" Text="10248" /> <asp:Button ID="btnFindOrder" runat="server" Text="Find Order" OnClick="BtnFindOrders_Click" /> <asp:UpdatePanel ID="updatePanel" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Orders" BackColor="lightblue" Width="95%" /> <asp:GridView id="gvOrderDetails" runat="server" DataSourceID="sqldsOrderDetails" AllowSorting="true" Width="95%" > <AlternatingRowStyle BackColor="aliceBlue" /> <HeaderStyle HorizontalAlign="Left" /> </asp:GridView> </ContentTemplate> </asp:UpdatePanel>
Post-Back Triggers
Post-back triggers are useful for ...
- Registering post-back controls inside of an UpdatePanel to reload the entire page instead of only the UpdatePanel's content.
This might not sound all that useful, however there were two occasions where I recently needed to explicitly define a control within the panel that reloaded the entire page
- I used this approach while building a file upload wizard. I wanted the wizard to move from page to page using ajax so only the wizard content was refreshed. However, I encountered a problem when one of the pages contained a FileUpload control. To work properly, this control requires a full post-back. To over come this issue, I programmatically marked the 'Next' button on the upload file page as a PostBackTrigger.
- I also used this approach for a panel that contained an export to excel button. Clicking the button caused the excel file to be downloaded to the client by writing the contents to the Response ASP.NET object. I needed to explicitly causes the complete page to reload because manually writing to the Response during an asynchronous post-back causes problems for the panel.
ChildrenAsTriggers
The ChildrenAsTriggers property is a boolean property that defaults to true. When this property is set to true, a post-back that originates from any control that is contained within the UpdatePanel, but not a nested UpdatePanel will cause the contents to update.
UpdateMode
The UpdateMode property of the UpdatePanel can be set to either Always or Conditional, but if neither are supplied it will default to Always. When the value is Always, a postback from any other control on the page will cause the contents of the panel to be updated. If the control that causes the post-back was marked as an asynchronous post-back trigger, only the contents of the panel is updated, otherwise the complete page - including the panel is updated.
| I know this seems intuitive, but you still need to be careful. If you have a page with two UpdatePanels, each using different buttons for their async triggers and you don't remember to explicitly set the UpdateMode attribute for both panels to Conditional both panels will be updated if either buttons are pressed. The following live example demonstrates this problem. The UpdatePanels are not explicitly set to Conditional, so any asynchronous post-back causes them to refresh. In the demo, sorting by the column header in the Customer grid causes both the Customers and the Orders to be refreshed. |
When the UpdateMode property is set to Conditional, the contents within the panel are updated during an asynchronous post-back when one of the following scenarios occurs:
- The Update() method is programmatically invoked on the server
- The post-back is caused by a control that is specified as the trigger for the panel
- The ChildrenAsTriggers property is set to true and a child control (that is not contained within a nested UpdatePanel) causes the post-back
Issues
* When the value of the UpdateMode property is set to Always, the ChildrenAsTriggers property can not be set to false otherwise you will receive the following runtime exception:
ChildrenAsTriggers cannot be set to false when UpdateMode is set to Always on UpdatePanel 'updatePanel1'.
* If you have two UpdatePanels on the page both pointing at the same control as a trigger, but one panel declares it as an asynchronous post-back trigger while the other declares it as a regular post-back trigger, the following exception will be generated at runtime:
Control with ID 'btn1' cannot be registered through both RegisterAsyncPostBackControl and RegisterPostBackControl. This can happen if you have conflicting triggers associated with the target control.
Comments
Good post. Especially the part about the UpdateMode property. I think too few people take the time to understand what they're actually doing when they start throwing multiple UpdatePanels onto their pages.
Regarding the file download scenario you mentioned as requiring a full postback, you might be interested in reading this post of mine: AJAX, file downloads, and IFRAMEs.
I have one parent user control and inside there are two child user control.first child control i have a button click on that button i need to refresh my second child control.how can i do on ajax
This is certainly very useful. Iam a newbie and have a question. I created a listbox inside the update Panel. The data gets populated and i need to save the values in this listbox to my DB. Does the UpdateMethod save the data, if the control i specify is the listbox? thanks in adv
an indepth explanation of update panel which helped me a lot during development. Thanks dude.
Matt - I have to do something very similar to this example for a project. Can you make the code for the live example pages available for download? Thanks.
Hi Matt, Its a great post! I tried implementing this into a content page and it doesn't load the gridview! It shows the loading animation and just sticks there. Can you let me know if there's anything to change to work it in content pages? Thanks!
Hi Matt, thanks for this great blog. I recently created a web user control which includes a ModalPopupExtender, a GridView, a TextBox and a button. I use this as a Lookup helper for company or product selection. The problem is, I registered "PageIndexChanged" event as AsyncTrigger. For the gridview I needed RowSelected event to do a postback, PageIndexChanged to do an asyncpostback. But this doesn't work. They both do async postback. Have you tried this before?
Thanks!
Hey Matt,
It's always nice to learn from your site. keep on good work