ptg 1664 CHAPTER 37 Building Templated Databound Controls LISTING 37.8 ShowProductForm.aspx <%@ Page Language=”C#” %> <%@ Register TagPrefix=”custom” Namespace=”myControls” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> void Page_Load() { if (!Page.IsPostBack) { ProductForm1.Name = “Laptop”; ProductForm1.Price = 433.12m; ProductForm1.DataBind(); } } protected void ProductForm1_ProductUpdated(object sender, EventArgs e) { lblName.Text = ProductForm1.Results[“Name”].ToString(); lblPrice.Text = ProductForm1.Results[“Price”].ToString(); } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show ProductForm</title> </head> <body> <form id=”form1” runat=”server”> <div> <custom:ProductForm id=”ProductForm1” Runat=”server” OnProductUpdated=”ProductForm1_ProductUpdated”> <EditItemTemplate> <asp:Label id=”lblName” Text=”Product Name:” AssociatedControlID=”txtName” Runat=”server” /> <asp:TextBox id=”txtName” From the Library of Wow! eBook ptg 1665 Creating Templated Controls Text=’<%# Bind(“Name”) %>’ Runat=”server” /> <br /><br /> <asp:Label id=”lblPrice” Text=”Product Price:” AssociatedControlID=”txtPrice” Runat=”server” /> <asp:TextBox id=”txtPrice” Text=’<%# Bind(“Price”) %>’ Runat=”server” /> <br /><br /> <asp:Button id=”btnUpdate” Text=”Update” Runat=”server” /> </EditItemTemplate> </custom:ProductForm> <hr /> New Product Name: <asp:Label id=”lblName” Runat=”server” /> <br /><br /> New Product Price: <asp:Label id=”lblPrice” Runat=”server” /> </div> </form> </body> </html> In the Page_Load() method in Listing 37.8, the ProductForm Name and Price properties are set. Next, the DataBind() is called to cause the ProductForm control to evaluate its databinding expressions. The ProductForm control’s EditItemTemplate includes Bind() expressions instead of Eval() expressions. You use Bind() expressions in a two-way databinding template. 37 From the Library of Wow! eBook ptg 1666 CHAPTER 37 Building Templated Databound Controls The EditItemTemplate includes a Button control. When you click the Button control, the ProductForm control’s OnBubbleEvent() method executes, the values are retrieved from the EditItemTemplate, and the ProductUpdated event is raised. The page in Listing 37.8 handles the ProductUpdated event and displays the new values with two Label controls (see Figure 37.3). FIGURE 37.3 Using a two-way databinding template. Creating Templated Databound Controls In this section, you learn how to build templated databound controls. A databound control can be bound to a DataSource control such as the SqlDataSource or ObjectDataSource controls. The ASP.NET Framework provides you with a number of base classes that you can use when creating a custom databound control. So, let’s look at some tables and figures. Table 37.1 lists the base control classes for all the standard ASP.NET databound controls. Figure 37.4 displays the inheritance hierarchy of all the new databound controls in ASP.NET Framework. Typically, you inherit from one of the leaf nodes. You create a control that derives from the base CompositeDataBoundControl, HierarchicalDataBoundControl, or ListControl class. From the Library of Wow! eBook ptg 1667 Creating Templated Controls This chapter concentrates on inheriting new controls from the base CompositeDataBoundControl class. This is the easiest base class to use when you want to display one or more database records and use templates. NOTE You learne d how to create c ont rol s that inherit from the base ListControl class in Chapter 10, “Using List Controls.” Creating a DivView Control Let’s start simple. In this section, we create a custom databound control named the DivView control, which displays a set of data items (database records) in HTML <div> tags. The DivView control inherits from the base CompositeDataBoundControl class and over- rides a single method of the base class. The DivView control overrides the base class’s CreateChildControls() method. The DivView control is contained in Listing 37.9. 37 FIGURE 37.4 Databound control inheritance hierarchy. TABLE 37.1 Base Databound Control Classes Control Base Control ListView DataBoundControl GridView, DetailsView, FormView CompositeDataBoundControl Menu, TreeView HierarchicalDataBoundControl DropDownList, ListBox RadioButtonList, CheckBoxList, BulletedList ListControl DataList, DataGrid BaseDataList Repeater Control From the Library of Wow! eBook ptg 1668 CHAPTER 37 Building Templated Databound Controls LISTING 37.9 DivView.cs using System; using System.Collections; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace AspNetUnleashed { public class DivView : CompositeDataBoundControl { private ITemplate _itemTemplate; [TemplateContainer(typeof(DivViewItem))] [PersistenceMode(PersistenceMode.InnerProperty)] public ITemplate ItemTemplate { get { return _itemTemplate; } set { _itemTemplate = value; } } protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding) { int counter = 0; foreach (object dataItem in dataSource) { DivViewItem contentItem = new DivViewItem(dataItem, counter); _itemTemplate.InstantiateIn(contentItem); Controls.Add(contentItem); counter++; } DataBind(false); return counter; } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Div; } } } From the Library of Wow! eBook ptg 1669 Creating Templated Databound Controls 37 public class DivViewItem : WebControl, IDataItemContainer { private object _dataItem; private int _index; public object DataItem { get { return _dataItem; } } public int DataItemIndex { get { return _index; } } public int DisplayIndex { get { return _index; } } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Div; } } public DivViewItem(object dataItem, int index) { _dataItem = dataItem; _index = index; } } } The DivView control supports an ItemTemplate used to format each of its data items. You are required to supply an ItemTemplate when you use the DivView control. All the work happens in the CreateChildControls() method. This is not the same CreateChildControls() method included in the base System.Web.UI.Control class. The DivView control overrides the CompositeDataBounControl’s CreateChildControls() method. From the Library of Wow! eBook ptg 1670 The CreateChildControls() method accepts the following two parameters: . dataSource—Represents all the data items from the data source. . dataBinding—Represents whether the CreateChildControls() method is called when the data items are retrieved from the data source. The CreateChildControls() method is called every time that the DivView control renders its data items. When the control is first bound to a DataSource control, the dataSource parameter represents the data items retrieved from the DataSource control. After a post- back, the dataSource parameter contains a collection of null values, but the correct number of null values. After a postback, the contents of the data items can be retrieved from View State. As long as the correct number of child controls is created, the Framework can rebuild the contents of the databound control. You can use the dataBinding parameter to determine whether the data items from the data source actually represent anything. Typically, the dataBinding parameter has the value True when the page first loads and the value False after each postback. The DataBind() method is called after the child controls are created. You must call the DataBind() method when a template includes databinding expressions. Otherwise, the databinding expressions are never evaluated. The page in Listing 37.10 illustrates how you can bind the DivView control to a SqlDataSource control. LISTING 37.10 ShowDivView.aspx <%@ Page Language=”C#” %> <%@ Register TagPrefix=”custom” Namespace=”AspNetUnleashed” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <style type=”text/css”> .movies { width:500px; } .movies div { border:solid 1px black; padding:10px; margin:10px; CHAPTER 37 Building Templated Databound Controls From the Library of Wow! eBook ptg 1671 Creating Templated Databound Controls 37 } </style> <title>Show DivView</title> </head> <body> <form id=”form1” runat=”server”> <div> <custom:DivView id=”lstMovies” DataSourceID=”srcMovies” CssClass=”movies” Runat=”Server”> <ItemTemplate> <h1><%# Eval(“Title”) %></h1> Director: <%# Eval(“Director”) %> </ItemTemplate> </custom:DivView> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Title, Director FROM Movies” Runat=”server” /> <br /> <asp:LinkButton id=”lnkReload” Text=”Reload” Runat=”server” /> </div> </form> </body> </html> In Listing 37.10, the SqlDataSource control represents the Movies database table. The DivView control includes an ItemTemplate that formats each of the columns from this database table (see Figure 37.5). From the Library of Wow! eBook ptg 1672 CHAPTER 37 Building Templated Databound Controls Summary This chapter was devoted to the topic of building templated databound controls. In the first part, you learned how to support templates in your custom controls. You learned how to create templates that support both one-way and two-way databinding expressions. You also learned how to create a default template for a control. The second half of this chapter focused on the topic of building databound controls. You learned how to create a simple DivView control that displays the records from a database table in a series of HTML <div> tags. FIGURE 37.5 Displaying database records with the DivView control. From the Library of Wow! eBook ptg CHAPTER 38 Using Server-Side ASP.NET AJAX IN THIS CHAPTER . The Ajax Vision . Server-Side Ajax versus Client- Side Ajax . Debugging Ajax Applications . Using the UpdatePanel Control . Using the Timer Control . Using the UpdateProgress Control . Summary Users of modern web applications have changed quite a bit since the first days of the web. When the web was new and when functional, commercial websites were few and far between, the users of web applications were a generally complacent and easy-to-please audience. Today, web application users don’t just want more, they demand more. They demand that websites be fast, respon- sive, and interactive. They don’t want an entire page to reload just because a small piece needs to be changed. Most important, they don’t want to sit and wait in front of an unresponsive user interface while background processing takes place. To meet the increasing demands of web users, a new tech- nology called AJAX (Asynchronous JavaScript and XML) was created. This enabled already-rendered web pages to make asynchronous calls and retrieve XML, which could then be used to modify the existing page. The first evidence of this type of technology actually showed up in Microsoft Outlook’s web access product. Since then, web application users have been demanding unprecedented levels of interac- tivity and responsiveness. The key to giving users this responsiveness lies in the combination of asynchronous messaging calls and JavaScript (or jQuery or any number of JavaScript-based frameworks). In this chapter you learn about one small piece of this puzzle: Microsoft’s server-side Ajax controls such as the UpdatePanel, a control that enables postbacks within a region of the page to modify only that portion of the page and not interrupt the user’s overall experience. We also provide an overview of two controls that support the UpdatePanel: the Timer and the UpdateProgress. From the Library of Wow! eBook . System.Web.UI.WebControls; namespace AspNetUnleashed { public class DivView : CompositeDataBoundControl { private ITemplate _itemTemplate; [TemplateContainer(typeof(DivViewItem))] [PersistenceMode(PersistenceMode.InnerProperty)]. Wow! eBook ptg CHAPTER 38 Using Server-Side ASP. NET AJAX IN THIS CHAPTER . The Ajax Vision . Server-Side Ajax versus Client- Side Ajax . Debugging Ajax Applications . Using the UpdatePanel Control (!Page.IsPostBack) { ProductForm1.Name = “Laptop”; ProductForm1.Price = 43 3.12m; ProductForm1.DataBind(); } } protected void ProductForm1_ProductUpdated(object sender, EventArgs e) { lblName.Text = ProductForm1.Results[“Name”].ToString();