Section 11.3. Making a Page Region Updateable


11.3. Making a Page Region Updateable

A list of Ajax advantages would most certainly contain something along the lines of: "Changing a section of a web page without performing a postback." In previous chapters, this was often done by retrieving data from the server and then using JavaScript and DOM to use this data and populate an element on the page.

One very neat feature of Atlas is the ability to perform partial page updates. That means that one section of a page is updated, like with a page reload, but without a complete page postback.refresh. Also, no JavaScript is required (from the developer); Atlas takes care of that.

The Atlas control that makes this possible is UpdatePanelcontrol. Everything inside an update panel works like a page within a page. The contents of the panel are refreshed from the server (using XMLHttpRequest, of course). However, from the programming model, it looks like a regular page refresh. If you 233re accessing Page.IsPostBack, this has the value TRue when an updateable portion of a page is refreshed from the server. All other events that are raised during ordinary postbacks are also raised for update panel refreshes.

You can think of an UpdatePanel as an iframe (internal frame in a web site, using the <iframe> HTML element) within a page. This section is reloaded and refreshed on its own. However the main advantage in comparison to using a regular iframe is that the ASP.NET page life cycle events are still raised, so programmatically, you only have one page, not two. This makes coding much easier and the architecture way less complex.


11.3.1. Updating a Section

The UpdatePanel control contains a content template (<ContentTemplate>), which, in turn, contains the controls and elements that make up the page. A good demonstration is the ASP.NET 2.0 GridView element, which is the successor of the ASP.NET 1.0 DataGrid element. Using ASP.NET 2.0 and Visual Studio 2005 (including the Visual Web Developer Express Edition), it's easy to configure a GridView control with sorting and editing. However, whenever you do anything with the gridsorting, paging, changing into edit mode and backa postback to the server occurs, including the mandatory page refresh. But if you put a GridView control within the UpdatePanel control's <ContentTemplate> section, you can have the same functionality without the page reloads. XMLHttpRequest and Atlas do the required magic.

So first, here is the GridView control within an UpdatePanel control (again assuming the AdventureWorks database). Note that this markup requires that the connection string for connecting with the AdventureWorks database is stored in Web.config. Visual Studio and Visual Web Developer take care of that for you automatically if you drag and drop a table (here: Purchasing.Vendor) from Database Explorer to the page in Design view.

 <atlas:UpdatePanel  runat="server">   <ContentTemplate>     <asp:GridView  runat="server"       AllowPaging="True"       AllowSorting="True"       AutoGenerateColumns="False"       DataKeyNames="VendorID" DataSource       EmptyDataText="There is no data to display.">     [...]     </asp:GridView>     <asp:SqlDataSource         runat="server"        ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString1 %>"...>     [...]     </asp:SqlDataSource>   </ContentTemplate> </atlas:UpdatePanel> 

If you provide an ID for the UpdatePanel control (which is not required, however), you even have SmartTag support in Design view of Visual Studio. However, currently the only SmartTag action is to add the ScriptManager to the page. The real convenience lies in the ability to drag a data table from Database Explorer into the UpdatePanel control. Figure 11-6 shows the UpdatePanel control in Design view.

Figure 11-6. The UpdatePanel control in Design view


Only one more step is required to use the UpdatePanel control: you must set the EnablePartialRendering property of the ScriptManager element to "true". Only then are the partial page refreshes possible.

 <atlas:ScriptManager       EnablePartialRendering="true"   runat="server"> </atlas:ScriptManager> 

To demonstrate that there is really no full-page refresh, we'll add a Label control to the page:

 <asp:Label  runat="server" /> 

This Label control will display the current time on the server. If there is a page refresh, code like the following will update the Label control.

 protected void Page_Load(object sender, EventArgs e) {   CurrentTime.Text = DateTime.Now.ToLongTimeString(); } 

Example 11-4 shows the complete code for this example.

Example 11-4. A GridView control that is updated without a page refresh

 UpdatePanel.aspx <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   protected void Page_Load(object sender, EventArgs e)   {     CurrentTime.Text = DateTime.Now.ToLongTimeString();   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">   <title>Atlas</title> </head> <body>   <form  runat="server">     <atlas:ScriptManager  EnablePartialRendering="true" runat="server">     </atlas:ScriptManager>     <asp:Label  runat="server" />     <atlas:UpdatePanel  runat="server">     <ContentTemplate>         <asp:GridView  runat="server" AllowPaging="True" AllowSorting="True"           AutoGenerateColumns="False" DataKeyNames="VendorID" DataSource           EmptyDataText="Es sind keine Datensätze zum Anzeigen vorhanden.">           <Columns>             <asp:CommandField ShowEditButton="True" />             <asp:BoundField DataField="VendorID" HeaderText="VendorID" ReadOnly="True" SortExpression="VendorID" />             <asp:BoundField DataField="AccountNumber" HeaderText="AccountNumber" SortExpression="AccountNumber" />             <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />             <asp:BoundField DataField="CreditRating" HeaderText="CreditRating" SortExpression="CreditRating" />             <asp:CheckBoxField DataField="PreferredVendorStatus" HeaderText="PreferredVendorStatus"               SortExpression="PreferredVendorStatus" />             <asp:CheckBoxField DataField="ActiveFlag" HeaderText="ActiveFlag" SortExpression="ActiveFlag" />             <asp:BoundField DataField="PurchasingWebServiceURL" HeaderText="PurchasingWebServiceURL"               SortExpression="PurchasingWebServiceURL" />             <asp:BoundField DataField="ModifiedDate" HeaderText="ModifiedDate" SortExpression="ModifiedDate" />           </Columns>         </asp:GridView>         <asp:SqlDataSource  runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString1 %>"           DeleteCommand="DELETE FROM [Purchasing].[Vendor] WHERE [VendorID] = @VendorID"           ProviderName="<%$ ConnectionStrings:AdventureWorksConnectionString1 .ProviderName %>"           SelectCommand="SELECT [VendorID], [AccountNumber], [Name], [CreditRating], [PreferredVendorStatus], [ActiveFlag], [PurchasingWebServiceURL], [ModifiedDate] FROM [Purchasing].[Vendor]"           UpdateCommand="UPDATE [Purchasing].[Vendor] SET [AccountNumber] = @AccountNumber, [Name] = @Name, [CreditRating] = @CreditRating, [PreferredVendorStatus] = @PreferredVendorStatus, [ActiveFlag] = @ActiveFlag, [PurchasingWebServiceURL] = @PurchasingWebServiceURL, [ModifiedDate] = @ModifiedDate WHERE [VendorID] = @VendorID">           <UpdateParameters>             <asp:Parameter Name="AccountNumber" Type="String" />             <asp:Parameter Name="Name" Type="String" />             <asp:Parameter Name="CreditRating" Type="Byte" />             <asp:Parameter Name="PreferredVendorStatus" Type="Boolean" />             <asp:Parameter Name="ActiveFlag" Type="Boolean" />             <asp:Parameter Name="PurchasingWebServiceURL" Type="String" />             <asp:Parameter Name="ModifiedDate" Type="DateTime" />             <asp:Parameter Name="VendorID" Type="Int32" />           </UpdateParameters>           <DeleteParameters>             <asp:Parameter Name="VendorID" Type="Int32" />           </DeleteParameters>         </asp:SqlDataSource>     </ContentTemplate>     </atlas:UpdatePanel>   </form> </body> </html> 

As Figure 11-7 and 11-8 show, the GridView control works just as you'd expect it to, but the timestamped Label control does not change. This proves that indeed all communication happens in the background.

Figure 11-7. Triggering a postback of the GridView control


Figure 11-8. Triggering the postback does not change the timestamp on top


When you use the drag-and-drop feature of Visual Studio and drop the Vendor table onto the page in Design view, you may get an ASP.NET error message in the browser, because even though Vendor is a unique table name, it is defined with a namespace in the database. The correct name is Purchasing.Vendor. Therefore, you may have to go through the automatically generated code and change all occurrences of [Vendor] with [Purchasing.Vendor].


11.3.2. Updating a Section at Timed Intervals

There are times when you might want to refresh the contents of an UpdatePanel control at regular intervals, not just in response to a user gesture. I remember an online chat on ASP.NET that I was conducting some years ago. One of the attendees asked how to use the Timer server control he found in Visual Studiofor ASP.NET pages. I answered the question by explaining the client-server model and JavaScript's options for time delays.

Now, a few years later and with Atlas at my disposal, I could give a different answer. The TimerControl element that comes with Atlas creates an abstraction layer for the associated JavaScript methods, window.setTimeout() and window.setInterval(). You provide an interval (measured in milliseconds, as the JavaScript methods expect, after which a Tick event occurs. Here is a TimerControl element that creates a new Tick event every five seconds:

 <atlas:TimerControl Interval="5000" runat="server" /> 

With the timer control, now you can trigger a refresh of the UpdatePanel whenever the tick event is raisedin other words, at regular intervals. This can be done programmatically; but as usual, there is a declarative way as well.

Within the UpdatePanel control, the <Triggers> element can be used to define event triggers that cause the UpdatePanel control to be refreshed. Whenever the trigger event occurs, the UpdatePanel runs through its refresh cycle. These two properties must be set:


ControlID

The name of the control that raises the event


EventName

The name of the event that triggers the refresh

You can also use the ControlValueTrigger element. There, you provide the ID of a control and one of its properties. When the specified property changes, the UpdatePanel control is refreshed:


 <atlas:ControlValueTrigger   Control   PropertyName="<property name>" /> 

To demonstrate the use of the timer with the UpdatePanel control, we'll move the Label control from the preceding example for displaying the current time into the UpdatePanel control.

So what will happen is the following:

  • When the page first loads, the Label control is set to the current time.

  • Every five seconds, the Tick event in the TimerControl occurs, which updates the contents of the UpdatePanel control (this is handled automatically by Atlas).

Example 11-5 shows the complete code for this example.

Example 11-5. Updating a panel at specific time intervals

 UpdatePanelTimer.aspx <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   protected void Page_Load(object sender, EventArgs e)   {     CurrentTime.Text = DateTime.Now.ToLongTimeString();   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">   <title>Atlas</title> </head> <body>   <form  runat="server">     <atlas:ScriptManager        EnablePartialRendering="true"       runat="server">     </atlas:ScriptManager>     <atlas:TimerControl  Interval="5000" runat="server" />     <atlas:UpdatePanel  runat="server">       <ContentTemplate>         <asp:Label  runat="server" />       </ContentTemplate>     <Triggers>     <atlas:ControlEventTrigger Control EventName="Tick" />     </Triggers>     </atlas:UpdatePanel>   </form> </body> </html> 

Figure 11-9 shows the results displayed when you load the page and allow it to update at intervals.

Figure 11-9. The timestamp is updated every five seconds


11.3.3. Programmatically Updating a Section at Timed Intervals

The most important method exposed by the UpdatePanel control is Update()as you may expect, it updates the panel. One way to use this method is to handle the TimerControl element's Tick event. In markup, you can do this:

 <atlas:TimerControl  Interval="5000"   OnTick="UpdateContents"   runat="server" /> 

Then in server code, you can write an ordinary ASP.NET event handler that calls the UpdatePanel control's Update method:

 protected void UpdateContents(object o, EventArgs e) {   if (new Random().Next(0, 4) == 1) {     UpdatePanel1.Update();   } } 

This code updates the panel (hence the display that the user sees) on average every fourth request. The Timer control causes a refresh call every five seconds; the code then randomly decides whether the current refresh call should update the panel. In the real world, you would probably check whether some data has changed (in the database, in a file), and then trigger the update.

The Atlas UpdatePanel control supports two modes, which you set in the Mode attribute of the control:


Always

The contents of the UpdatePanel control are refreshed whenever a postback occurs (default behavior).


Conditional

The contents of the UpdatePanel control are only refreshed when a trigger is used or the UpdatePanel's Update() method is called (as in this example).

Generally, the Conditional mode transfers less data between client and server, optimizing the UpdatePanel control's performance. So whenever possible (i.e., if you use triggers or Update()), use Mode="Conditional".

Example 11-6 shows the complete code for an UpdatePanel control being refreshed at a random interval, with changes highlighted.

Example 11-6. Programmatically updating a panel

 UpdatePanelTimerCode.aspx <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   private void UpdateContents(object o, EventArgs e)   {     if (new Random().Next(0, 4) == 1)     {     UpdatePanel1.Update();     }   }   protected void Page_Load(object sender, EventArgs e)   {     CurrentTime.Text = DateTime.Now.ToLongTimeString();   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head  runat="server">   <title>Atlas</title> </head> <body>   <form  runat="server">     <atlas:ScriptManager         EnablePartialRendering="true"        runat="server">     </atlas:ScriptManager>     <atlas:TimerControl  Interval="5000"     OnTick="UpdateContents"       runat="server" />     <atlas:UpdatePanel  runat="server"       Mode="Conditional">       <ContentTemplate>         <asp:Label  runat="server" />       </ContentTemplate>     </atlas:UpdatePanel>   </form> </body> </html> 

11.3.4. Displaying a Wait Screen

Another nice feature of UpdatePanel is its ability to display a wait screen while new data in the panel is loaded from the server. Especially when generating this data on the server takes a lot of time (consider complex database operations, for instance), a simple "loading" banner tells the user that his request is being processed and may also hinder repeated form submissions.

In the following example, we emulate a slow server script and then let Atlas display a wait screen while the server script is executed.

First of all, the slow server script is written. What it basically does is wait five seconds:

 void WaitFiveSeconds(object o, EventArgs e) {   System.Threading.Thread.Sleep(5000); } 

This script is triggered by a button within an UpdatePanel control. So when the button is clicked, the server script runs for five seconds:

 <atlas:UpdatePanel  runat="server">   <ContentTemplate>     <asp:Button  runat="server"       Text="Do something" OnClick="WaitFiveSeconds" />   </ContentTemplate> </atlas:UpdatePanel> 

Finally, the wait screen is implemented. For this task, Atlas provides the UpdateProgress control. Within this control, the <ProgressTemplate> element expects HTML (or ASP.NET) markup. Whenever the UpdatePanel on the page is refreshed, the contents of the UpdateProgress control's <ProgressTemplate> template is shown; after the UpdatePanel has been refreshed, the <ProgressTemplate> content is made invisible again. Some web sites use an hourglass image in their waiting screens; others just display text such as "loading...".

 <atlas:UpdateProgress  runat="server">   <ProgressTemplate>     <div style="position: absolute; left: 200px; top: 150px; border: solid 2px black;">       Loading ... Please stand by ...     </div>   </ProgressTemplate> </atlas:UpdateProgress> 

Only one UpdatePanel element is allowed per page, so there is no need to link UpdatePanel and UpdateProgress; Atlas figures out automatically that they belong together. Example 11-7 contains the complete code for this example, and Figure 11-10 shows the output when the page is run and the button is clicked, causing a five-second long refresh within the UpdatePanel.

Example 11-7. A wait screen for the UpdatePanel

 UpdateProgress.aspx <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   void WaitFiveSeconds(object o, EventArgs e)   {     System.Threading.Thread.Sleep(5000);   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">   <title>Atlas</title> </head> <body>   <form  runat="server">     <atlas:ScriptManager  runat="server"       EnablePartialRendering="true" />     <atlas:UpdatePanel  runat="server">       <ContentTemplate>         <asp:Button  runat="server"           Text="Do something" OnClick="WaitFiveSeconds" />       </ContentTemplate>     </atlas:UpdatePanel>     <atlas:UpdateProgress  runat="server">       <ProgressTemplate>         <div style="position: absolute; left: 200px; top: 150px; border: solid 2px black;">         Loading ... Please stand by ...         </div>       </ProgressTemplate>     </atlas:UpdateProgress>   </form> </body> </html> 

Figure 11-10. The wait screen appears while the contents of the UpdatePanel control are refreshed


Extending the Extender

Since this chapter has been all about extending stuff, it's worth noting that you can extend the extenders, which means adding custom functionality to them. Basically, you have to inherit from two classes to achieve this:

  • AutoCompleteExtender

  • AutoCompleteProperties

Then you can add new properties to AutoCompleteProperties and reflect these changes in the Render() method of AutoCompleteExtender.

Since the source code of Atlas is not available, a reflector like the one at http://www.aisto.com/roeder/dotnet can be a salvation. The blog entry at http://aspadvice.com/blogs/garbin/archive/2006/01/02/14518.aspx shows how to implement a MinimumPrefixLength property. It allows Atlas to call the lookup web service even with a lower number of characters entered into the text field, if desired.

With the Atlas Control Toolkit, Microsoft provides an easy-to-use template for creating custom extenders. See Chapter 14 for more details on that.


It is possible that Microsoft will add more extenders in the future. However, always be aware of potential side issues. For instance, file uploads currently are problematic when done within an UpdatePanel control. Therefore, use these effects carefully. If a regular <iframe> HTML element suffices, you do not have to rely on Atlas and thereby make your application a bit harder to debug if something goes wrong.




Programming Atlas
Programming Atlas
ISBN: 0596526725
EAN: 2147483647
Year: 2006
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net