Evjen c19.tex V2 - 01/28/2008 3:08pm Page 918 Chapter 19: ASP.NET AJAX End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > UpdatePanel Control < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < asp:UpdatePanel ID="UpdatePanel1" runat="server" > < ContentTemplate > < asp:Label ID="Label1" runat="server" >< /asp:Label > < br / > < br / > < asp:Button ID="Button1" runat="server" Text="Click to initiate async request" OnClick="Button1_Click" / > < /ContentTemplate > < /asp:UpdatePanel > < /div > < /form > < /body > < /html > C# < %@ Page Language="C#" % > < script runat="server" > protected void Button1_Click(object sender, EventArgs e) { Label1.Text = "This button was clicked on " + DateTime.Now.ToString(); } < /script > In this case, the Label and Button server controls are contained within the UpdatePanel server con- trol. The < asp:UpdatePanel > element has two possible sub-elements: < ContentTemplate > and the < Triggers > elements. Any content that needs to be changed with the asynchronous page postbacks should be contained within the < ContentTemplate > section of the UpdatePanel control. By default, any type of control trigger (something that would normally trigger a page postback) that is contained within the < ContentTemplate > section instead causes the asynchronous page postback. That means, in the case of Listing 19-13, the button on the page will trigger an asynchronous page post- back instead of a full-page postback. Each click o n the button changes the time displayed in the Label control. The < Triggers > Element Listing 19-13 demonstrates one of the big issues with this model: When the asynchronous postback occurs, you are not only sending the date/time value for the Label control, but you are also sending back the entire code for the button that is on the page. 918 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 919 Chapter 19: ASP.NET AJAX 265|updatePanel|UpdatePanel1| < span id="Label1" > This button was clicked on 11/18/2007 11:45:21 AM < /span > < br / > < br / > < input type="submit" name="Button1" value="Click to initiate async request" id="Button1" / > |164|hiddenField|__VIEWSTATE|/wEPDwUKLTU2NzQ4MzIwMw9kFgICBA9kFgICAw9kFgJmD2QWAgIBDw 8WAh4EVGV4dAUxVGhpcyBidXR0b24gd2FzIGNsaWNrZWQgb24gMTEvMTgvMjAwNyAxMTo0NToyMSBBTWRkZ KJIG4WwhyQvUwPCX4PxI5FEUFtC|48|hiddenField|__EVENTVALIDATION|/wEWAgL43YXdBwKM54rGBl I52OYVl/McOV61BYd/3wSj+RkD|0|asyncPostBackControlIDs|||0|postBackControlIDs|||13| updatePanelIDs||tUpdatePanel1|0|childUpdatePanelIDs|||12|panelsToRefreshIDs|| UpdatePanel1|2|asyncPostBackTimeout||90|22|formAction||SimpleUpdatePanel.aspx|11| pageTitle||UpdatePanel| This bit of code that is sent back to the client via the asynchronous postback shows that the entire section contained within the UpdatePanel control is reissued. You can slim down your pages by including only the portions of the page that are actually updating. If you take the button outside of the < Content Template > section of the UpdatePanel control, then you have to include a < Triggers > section within the control. The reason for this is that while the content that you want to change with the asynchronous postback is all contained within the < ContentTemplate > section, you have to tie up a page event to cause the postback to occur. This is how the < Triggers > section of the UpdatePanel control is used. You use this section of the control to specify the various triggers that initiate an asynchronous page postback. Using the < Triggers > element within the UpdatePanel control, you can rewrite Listing 19-13 as shown in Listing 19-14. Listing 19-14: Using a trigger to cause the asynchronous page postback VB < %@ Page Language="VB" % > < script runat="server" > Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Label1.Text = "This button was clicked on " & DateTime.Now.ToString() End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > UpdatePanel < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < asp:UpdatePanel ID="UpdatePanel1" runat="server" > < ContentTemplate > < asp:Label ID="Label1" runat="server" >< /asp:Label > < /ContentTemplate > Continued 919 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 920 Chapter 19: ASP.NET AJAX < Triggers > < asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" / > < /Triggers > < /asp:UpdatePanel > < br / > < br / > < asp:Button ID="Button1" runat="server" Text="Click to initiate async request" OnClick="Button1_Click" / > < /div > < /form > < /body > < /html > C# < %@ Page Language="C#" % > < script runat="server" > protected void Button1_Click(object sender, EventArgs e) { Label1.Text = "This button was clicked on " + DateTime.Now.ToString(); } < /script > In this case, the Button control and t he HTML elements are outside of the < ContentTemplate > section of the UpdatePanel control and therefore will not be sent back to the client for each asynchronous page post- back. The only item contained in the < ContentTemplate > section is the only item on the page that needs to change with the postbacks — the Label control. Tying this all together is the < Triggers > section. The < Triggers > section can contain two possible controls: AsyncPostBackTrigger and PostBackTrig- ger. In this case, the AsyncPostBackTrigger is used. The PostBackTrigger control will cause a full page postback, whereas the AsyncPostBackTrigger control will cause only an asynchronous page postback (obviously as described by the names of the controls). As you can see from the example in Listing 19-14, which uses the AsyncPostBackTrigger element, only two attributes are used to tie the Button control to the trigger for the asynchronous postback: the Con- trolID and the EventName attributes. The control you want to act as the initiator of the asynchronous page postback is put here (the control’s name as specified by the control’s ID attribute). The Event- Name attribute’s value is the name of the event for the control that is specified in the ControlID that you want to be called in the asynchronous request from the client. In this case, the Button control’s Click() event is called and this is the event that changes the value of the control that resides within the < ContentTemplate > section of the UpdatePanel control. Running this page and clicking on the button gives you a smaller asynchronous response back to the client. 108|updatePanel|UpdatePanel1| < span id="Label1" > This button was clicked on 11/18/2007 11:58:56 AM < /span > |164|hiddenField|__VIEWSTATE|/wEPDwUKMjA2NjQ2MDYzNw9kFgICBA9kFgICAw9kFgJmD2QWAgIBDw 8WAh4EVGV4dAUxVGhpcyBidXR0b24gd2FzIGNsaWNrZWQgb24gMTEvMTgvMjAwNyAxMTo1ODo1NiBBTWRkZ PJA9uj9wwRaasgTrZo85rVvLnoi|48|hiddenField|__EVENTVALIDATION|/wEWAgKK3YDTDAKM54rGBq rbjV4/u4ks3aKsn7Xz8xNFE8G/|7|asyncPostBackControlIDs||Button1|0|postBackControlIDs| 920 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 921 Chapter 19: ASP.NET AJAX ||13|updatePanelIDs||tUpdatePanel1|0|childUpdatePanelIDs|||12|panelsToRefreshIDs|| UpdatePanel1|2|asyncPostBackTimeout||90|22|formAction||SimpleUpdatePanel.aspx|11| pageTitle||UpdatePanel| Although not considerably smaller than the previous example, it is smaller and t he size similarity is really due to the size of the page used in this example (pages that are more voluminous would show more dramatic improvements). Pages with heavy content associated with them can show some dramatic size reductions depending on how you structure your pages with the UpdatePanel control. Building Triggers Using Visual Studio 2008 If you like to work on the design surface of Visual Studio when building your ASP.NET pages, you will find that there is good support for building your ASP.NET AJAX pages, including the creation of triggers in the UpdatePanel control. To see this in action, place a single UpdatePanel server control on your page and view the control in t he Properties dialog within Visual Studio. The Triggers item in the list has a button next to it that allows you t o modify the items associated with it. T his is illustrated in Figure 19-11. Figure 19-11 Clicking on the button in the Properties dialog launches the UpdatePanelTrigger Collection Editor, as shown in Figure 19-12. This editor allows you to add any number of triggers and to associate them to a control and a control event very easily. Clicking the OK button here adds the trigger to the < Triggers > section of your UpdatePanel control. 921 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 922 Chapter 19: ASP.NET AJAX Figure 19-12 The UpdateProgress Control The final server control in the AJAX Extensions section of Visual Studio 2008 is the UpdateProgress control. Some asynchronous postbacks take some time to execute because of the size of the response or because of the computing time required to get a result together to send back to the client. T he UpdatePro- gress control allows you to provide a visual signifier to the clients to show that indeed work is being done and they will get results soon (and that the browser simply didn’t just lock up). Listing 19-15 shows a textual implementation of the UpdateProgress control. Listing 19-15: Using the UpdateProgess control to show a text message to the client VB < %@ Page Language="VB" % > < script runat="server" > Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) System.Threading.Thread.Sleep(10000) Label1.Text = "This button was clicked on " & DateTime.Now.ToString() End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > 922 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 923 Chapter 19: ASP.NET AJAX < title > UpdatePanel < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < asp:UpdateProgress ID="UpdateProgress1" runat="server" > < ProgressTemplate > An update is occurring < /ProgressTemplate > < /asp:UpdateProgress > < asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" > < ContentTemplate > < asp:Label ID="Label1" runat="server" >< /asp:Label > < /ContentTemplate > < Triggers > < asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" / > < /Triggers > < /asp:UpdatePanel > < br / > < br / > < asp:Button ID="Button1" runat="server" Text="Click to initiate async request" OnClick="Button1_Click" / > < /div > < /form > < /body > < /html > C# < %@ Page Language="C#" % > < script runat="server" > protected void Button1_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(10000); Label1.Text = "This button was clicked on " + DateTime.Now.ToString(); } < /script > To add some delay to the response (in order to simulate a long running computer process) the Thread. Sleep() method is called. From here, you add an UpdateProgess control to the part of the page where you want the update message to be presented. In this case, the UpdateProgress control was added above the UpdatePanel server control. This control does not go inside the UpdatePanel control; instead, it sits outside of the control. However, like the UpdatePanel control, the UpdateProgress control is a template control. The UpdateProgress control has only a single sub-element: the < ProgressTemplate > element. Whatever you place in this section of the control will appear when the UpdateProgress control is triggered. In this case, the only item present in this section of the control is some text. When you run this page, you will get the update shown in Figure 19-13. 923 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 924 Chapter 19: ASP.NET AJAX Figure 19-13 The text will appear immediately in this case and will not disappear until the asynchronous postback has finished. The code you put in the < ProgressTemplate > section is actually contained in the page, but its display is turned off through CSS. < div id="UpdateProgress1" style="display:none;" > An update is occurring < /div > Controlling When the Message Appears Right now, the UpdateProgress appears as soon as the button is clicked. However, some of yo ur processes might not take that long and you might not always want a progress notification going out to the client. The UpdateProgress control includes a DisplayAfter attribute, which allows you to control when the progress update message appears. The use of the DisplayAfter attribute is shown in Listing 19-16. Listing 19-16: Using the DisplayAfter attribute < asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="5000" > < ProgressTemplate > An update is occurring < /ProgressTemplate > < /asp:UpdateProgress > The value of the DisplayAfter property is a number that represents the number of milliseconds that the UpdateProgress control will wait until it displays what is contained within the < ProgressTemplate > section. The code in Listing 19-16 specifies that the text found in the < ProgressTemplate > section will not be displayed for 5,000 milliseconds (5 seconds). Adding an Image to the < ProcessTemplate > The previous examples which make use of the UpdateProgress control use this control with text, but you can put anything you want within this template control. For instance, you can put a spinning wheel image that will show the end user that the request is being processed. The use of the image is shown in Listing 19-17. 924 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 925 Chapter 19: ASP.NET AJAX Listing 19-17: Using an image in the <ProcessTemplate> section < asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="5000" > < ProgressTemplate > < asp:Image ID="Image1" runat="server" ImageUrl="~/spinningwheel.gif" / > < /ProgressTemplate > < /asp:UpdateProgress > Just as the in the text approach, the code for the image is already placed on the client’s page instance and is just turned off via CSS. < div id="UpdateProgress1" style="display:none;" > < img id="Image1" src="spinningwheel.gif" style="border-width:0px;" / > < /div > Using Multiple UpdatePanel Controls So far, this chapter has showed you how to work with a single UpdatePanel control, but it is important to realize that you can have multiple UpdatePanel controls on a single page. This, in the end, will give you the ability to control the output to specific regions of the page when you want. An example of using more than a single UpdatePanel control is presented in Listing 19-18. Listing 19-18: Using more than one UpdatePanel control VB < %@ Page Language="VB" % > < script runat="server" > Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Label1.Text = "Label1 was populated on " & DateTime.Now.ToString() Label2.Text = "Label2 was populated on " & DateTime.Now.ToString() End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > Multiple UpdatePanel Controls < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < asp:UpdatePanel ID="UpdatePanel1" runat="server" > < ContentTemplate > < asp:Label ID="Label1" runat="server" >< /asp:Label > < /ContentTemplate > < Triggers > < asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" / > < /Triggers > < /asp:UpdatePanel > Continued 925 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 926 Chapter 19: ASP.NET AJAX < asp:UpdatePanel ID="UpdatePanel2" runat="server" > < ContentTemplate > < asp:Label ID="Label2" runat="server" >< /asp:Label > < /ContentTemplate > < /asp:UpdatePanel > < br / > < br / > < asp:Button ID="Button1" runat="server" Text="Click to initiate async request" OnClick="Button1_Click" / > < /div > < /form > < /body > < /html > C# < %@ Page Language="C#" % > < script runat="server" > protected void Button1_Click(object sender, EventArgs e) { Label1.Text = "Label1 was populated on " + DateTime.Now; Label2.Text = "Label2 was populated on " + DateTime.Now; } < /script > This is an interesting page. There are two UpdatePanel controls on the page: UpdatePanel1 and UpdatePanel2 . Each of these controls contains a single Label control that at one point can take a date/time value from a server response. The UpdatePanel1 control has an associated trigger: the Button control on the page. When this but- ton is clicked, the Button1_Click() event triggers and does its job. If you run this page, both of the UpdatePanel controls a re updated according t o the Button1_Click() event. This is illustrated in Figure 19-14. Figure 19-14 926 Evjen c19.tex V2 - 01/28/2008 3:08pm Page 927 Chapter 19: ASP.NET AJAX Both UpdatePanel sections were updated with the button-click event because, by default, all Update- Panel controls on a single page update with each asynchronous postback that occurs. This means that the postback that occurred with the Button1 button control also causes a postback to occur with the UpdatePanel2 control. You can actually control this behavior through the UpdatePanel’s UpdateMode property. The Update- Mode property can take two possible enumerations — Always and Conditional .Ifyoudonotsetthis property, it uses the value of Always , meaning that each UpdatePanel control always updates with each asynchronous request. The other option is to set the property to Conditional . This means that the UpdatePanel updates only if one of the trigger conditions is met. For an example of this, change the UpdatePanel controls on the page so that they are now using an UpdateMode of Conditional , as shown in Listing 19-19. Listing 19-19: Using more than one UpdatePanel control VB < %@ Page Language="VB" % > < script runat="server" > Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Label1.Text = "Label1 was populated on " & DateTime.Now.ToString() Label2.Text = "Label2 was populated on " & DateTime.Now.ToString() End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > Multiple UpdatePanel Controls < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" > < ContentTemplate > < asp:Label ID="Label1" runat="server" >< /asp:Label > < /ContentTemplate > < Triggers > < asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" / > < /Triggers > < /asp:UpdatePanel > < asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional" > < ContentTemplate > < asp:Label ID="Label2" runat="server" >< /asp:Label > < /ContentTemplate > < /asp:UpdatePanel > < br / > < br / > Continued 927 . that initiate an asynchronous page postback. Using the < Triggers > element within the UpdatePanel control, you can rewrite Listing 19- 13 as shown in Listing 19-14. Listing 19-14: Using. ASP. NET pages, you will find that there is good support for building your ASP. NET AJAX pages, including the creation of triggers in the UpdatePanel control. To see this in action, place a single. will get the update shown in Figure 19- 13. 9 23 Evjen c19.tex V2 - 01/28/2008 3: 08pm Page 924 Chapter 19: ASP. NET AJAX Figure 19- 13 The text will appear immediately in this case and will not disappear