The first thing to do for using an UpdatePanel is to add a ScriptManager to the page. You can only add one and you need at least one, so you can add it to the MasterPage or just to the page using AJAX (notice the ScriptManager will add some extra scripts to your page making it slower). You can also use a ScriptManagerProxy, but that’s another story, let’s focus on UpdatePanels.
Adding a basic UpdatePanel
To add a basic UpdatePanel that will refresh without refreshing all the page and speed up your website just add this to your code after having added a ScriptManager:
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="BTNChangeText" runat="server" Text="Change" onclick="BTNChangeText_Click" /> <asp:Label ID="lbText" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> </asp:UpdatePanel>
And this other to your back code:
protected void BTNChangeText_Click(object sender, EventArgs e) { lbText.Text = "Text changed."; }
With just that the UpdatePanel will work using its default options and the text will be changed asyncronously. Now, you can use this to make a part of the page to work as if it were an iframe but without using frames.
Refreshing the UpdatePanel using external controls
In the last example we saw that we can use a control inside the UpdatePanel, like a button, to fire and by default it will be an asynchronous postback, but, what if we want an outside the UpdatePanel control to refresh it? For doing that we have the triggers.
Use this code in the front end:
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="BTNChangeText" runat="server" Text="Change" onclick="BTNChangeText_Click" /> <asp:Label ID="lbText" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnOutside" EventName="Click" /> </Triggers> </asp:UpdatePanel> <asp:Button ID="btnOutside" runat="server" Text="Change from outside" onclick="btnOutside_Click" />
And this in the back end:
protected void BTNChangeText_Click(object sender, EventArgs e) { lbText.Text = "Text changed from inside the UpdatePanel."; UpdatePanel1.Update(); } protected void btnOutside_Click(object sender, EventArgs e) { lbText.Text = "Text changed from outside the UpdatePanel."; }
As you can see, there is a button outside the UpdatePanel that will change the text inside it and now, at the bottom of the UpdatePanel, I’ve added a trigger to set that the outside button will asynchoronously refresh this UpdatePanel when clicked. If you don’t add the trigger the button will refresh all the page instead than just the Update Panel.
Using multiple UpdatePanels and conditional postbacks
Until now, we have been using just 1 UpdatePanel, which made it easy to handle its asynchronous postbacks. Now, we are going to add a second UpdatePanel to the page and see what happens:
This in the FrontEnd:
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="BTNChangeText" runat="server" Text="Change" onclick="BTNChangeText_Click" /> <asp:Label ID="lbText" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnOutside" EventName="Click" /> </Triggers> </asp:UpdatePanel> <asp:Label ID="lbOutside" runat="server" Text="Label outside."></asp:Label> <asp:Button ID="btnOutside" runat="server" Text="Change from outside" onclick="btnOutside_Click" /> <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Always"> <ContentTemplate> <asp:Button ID="btnAtUpdatePanel2" runat="server" Text="Change" onclick="btnAtUpdatePanel2_Click" /> <asp:Label ID="lbAtUpdatePanel2" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> </asp:UpdatePanel>
This in the Backend:
protected void btnAtUpdatePanel2_Click(object sender, EventArgs e) { lbAtUpdatePanel2.Text = "Text changed."; lbText.Text = "Text changed from another UpdatePanel."; lbOutside.Text = "Text changed."; }
Interestingly, when we update the UpdatePanel2 we can also change the label in the UpdatePanel1, but not the one outside any UpdatePanel. How is that possible? Well, UpdatePanels have a property to set if they will be postbacked and refreshed only under certain conditions or if they should be postbacked and refreshed allways. And by default, this property is set to always. So, when we make a full postback they will obviously be refreshed, but when we do any asynchronous postback for any updatePanel in the page all of the updatePanels in the page will also postback with it, unless we set their UpdateMode property to Conditional.
If we set the UpdateMode to Conditional we will make the partial request quicker since we will not be refreshing all the UpdatePanels in the page. And we are using UpdatePanels to make requests quicker so… it seems logic to use a conditional UpdateMode. They are set to “Always” by default to make the use of the UpdatePanel easier not having to add any trigger to make it work.
Setting the ChildrenAsTriggers property
By default, this property is set to true. This means any control inside the UpdatePanel will act as a trigger control and update it when fired. You can only set it to false if the UpdateMode is set to Conditional. If you set it to false the controls inside the UpdatePanel will make an asynchronous postback, but the UpdatePanel will not be refreshed.
This is very interesting since you can make one of those buttons do some stuff in the server without having to refresh any data back, or you can trigger another UpdatePanel but not the one in which the control is inside.
Refreshing an UpdatePanel from another UpdatePanel
Taking that last idea I’ve made this:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false"> <ContentTemplate> <asp:Button ID="BTNChangeText" runat="server" Text="Change" onclick="BTNChangeText_Click" /> <asp:Label ID="lbText" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnOutside" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="btnAtUpdatePanel2" EventName="Click" /> </Triggers> </asp:UpdatePanel> <asp:Label ID="lbOutside" runat="server" Text="Label outside."></asp:Label> <asp:Button ID="btnOutside" runat="server" Text="Change from outside" onclick="btnOutside_Click" /> <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Always"> <ContentTemplate> <asp:Button ID="btnAtUpdatePanel2" runat="server" Text="Change" onclick="btnAtUpdatePanel2_Click" /> <asp:Label ID="lbAtUpdatePanel2" runat="server" Text="Initial Text"></asp:Label> </ContentTemplate> </asp:UpdatePanel>
And this in the back end:
protected void BTNChangeText_Click(object sender, EventArgs e) { lbText.Text = "Text changed from inside the UpdatePanel."; lbOutside.Text = "Text changed."; } protected void btnOutside_Click(object sender, EventArgs e) { lbText.Text = "Text changed from outside the UpdatePanel."; lbOutside.Text = "Text changed."; } protected void btnAtUpdatePanel2_Click(object sender, EventArgs e) { lbAtUpdatePanel2.Text = "Text changed."; lbText.Text = "Text changed from another UpdatePanel."; lbOutside.Text = "Text changed."; }
Notice that with the properties UpdateMode=”Conditional” and ChildrenAsTriggers=”false” the UpdatePanel1 can launch asynchronous post backs (you can debug and see) but cannot refresh itself. Instead, the second UpdatePanel and the button outside them can update the UpdatePanel1 because they are into its triggers.
The UpdatePanel1 can also update the UpdatePanel2 since this second one has the UpdateMode=”Always” and it will be refreshed on any asynchronous request.
So, you have two ways of refreshing an UpdatePanel from another: setting its UpdateMode to always so it will be refreshed on any postback, or add a trigger with the control to fire the postback in it.
Updating from BackEnd
Now Imagine we want, under certain conditions, to refresh the UpdatePanel1 and we want to decide this in the back end. We can call its Update() event to make it be refreshed even when it wasn’t supposed to. Using the last example where its own button couldn’t refresh the UpdatePanel1 we can add this line to the code and make it possible in Back End:
protected void BTNChangeText_Click(object sender, EventArgs e) { lbText.Text = "Text changed from inside the UpdatePanel."; lbOutside.Text = "Text changed."; UpdatePanel1.Update(); }
Check it and see how despite its UpdateMode is set to Conditional, and its ChildrenAsTriggers to false, it is updated thanks to the call to its Update() event.