This demo binds the publishers table to a DataList, allows users to select a color with which the publisher name will be rendered, and then redraws the list with the newly selected colors. You can see the demo below, in Figure 6.4, as it first appears. Figure 6.4. The DataList Demo Shows How to Use Embedded Server Controls in a DataList.The User InterfaceAt the heart of the user interface is a DataList object named Publishers. Below the DataList is a Label named ErrorMessage that's used to alert users to any exception messages that have been caught. And below that is a Button that fires an event handler. The DataList has four columns when it renders: one for the publisher's name, one for the publisher's city, one for the publisher's country, and one for the list of colors. Within the DataList are two server controls: a Label named pub that contains the list of publishers, and a DropDownList named StyleSelector that contains a list of colors. The DataList code from the .aspx file is below. A discussion of the code follows the code listing. <asp:datalist runat="server" BorderWidth="1"> <HeaderTemplate> <tr> <th bgcolor="Thistle"> <font color="white">Publisher</font> </th> <th bgcolor="Thistle"> <font color="white">City</font> </th> <th bgcolor="Thistle"> <font color="white">Country</font> </th> <th bgcolor="Thistle"> <font color="white">Font Color</font> </th> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td> <asp:Label Runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "pub_name") %>' /> </td> <td> <%# DataBinder.Eval(Container.DataItem, "city") %> </td> <td> <%# DataBinder.Eval(Container.DataItem, "country") %> </td> <td> <asp:DropDownList Runat="server"> <asp:ListItem>Black</asp:ListItem> <asp:ListItem>Red</asp:ListItem> <asp:ListItem>Green</asp:ListItem> <asp:ListItem>Blue</asp:ListItem> </asp:DropDownList> </td> </tr> </ItemTemplate> </asp:datalist> First, notice that there are no <table> or </table> tags. That's because DataLists automatically render these. In the code above, the HeaderTemplate contains the table row for the table's heading. It renders as follows in Figure 6.5: Figure 6.5. The Table Has a Heading.The code that produced the table heading is as follows: <tr> <th bgcolor="Thistle"> <font color="white">Publisher</font> </th> <th bgcolor="Thistle"> <font color="white">City</font> </th> <th bgcolor="Thistle"> <font color="white">Country</font> </th> <th bgcolor="Thistle"> <font color="white">Font Color</font> </th> </tr> The ItemTemplate has four columns. The first column contains the publisher name in a Label named pub. It's populated with the DataBinder.Eval(Container.DataItem, "pub_Name") expression. The entire Label code is as follows: <asp:Label Runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "pub_name") %>' /> The second and third column simply use the DataBinder.Eval() method to populate the columns with data. The data is not included in a server control, and the second and third columns contain no server controls. The fourth column contains a DropDownList with four colors. The color selection determines the color with which the publisher name (in the first column) is rendered. The DropDownList code is as follows: <asp:DropDownList Runat="server"> <asp:ListItem>Black</asp:ListItem> <asp:ListItem>Red</asp:ListItem> <asp:ListItem>Green</asp:ListItem> <asp:ListItem>Blue</asp:ListItem> </asp:DropDownList> The Code behind the DataList DemoThere are two methods behind the DataList demo that we'll take a look at. The first is the Page_Load() method, and the second is the RedrawDataList_Click() method. Both methods are described in the next two sections. The Page_Load() Method Of The DataList DemoThe code for the Page_Load() method follows. A discussion of the code is immediately below it. C#private void Page_Load(object sender, System.EventArgs e) { // Only populate the Repeater if this is not a post back. if( !IsPostBack ) { // Create a connection object. SqlConnection objConnection = new SqlConnection("server=localhost;database=pubs;uid=sa;pwd="); // Use a try/catch/finally construct to // gracefully handle errors. try { // Open the connection. objConnection.Open(); // Create the command object. We'll select all // publisher name, city, and country. SqlCommand objCommand = new SqlCommand( "SELECT pub_name,city,country FROM publishers " + "ORDER BY pub_name", objConnection ); // Populate a reader. SqlDataReader objReader = objCommand.ExecuteReader(); // Set the DataLists's data source and then // call the DataBind() method. Publishers.DataSource = objReader; Publishers.DataBind(); // Close the reader. objReader.Close(); } catch( Exception ex ) { // Display the error message to the reader. ErrorMessage.Text = ex.Message.ToString(); } finally { // See if the connection is open. if( objConnection.State == ConnectionState.Open ) { // Close it if it is open. objConnection.Close(); } } } }VB Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Only populate the DataList if this is not a post back. If Not IsPostBack Then ' Create a connection object. Dim objConnection As _ New SqlConnection("server=localhost;database=pubs;uid=sa;pwd=s") ' Use a try/catch/finally construct to ' gracefully handle errors. Try ' Open the connection. objConnection.Open() ' Create the command object. We'll select all ' publisher name, city, and country. Dim objCommand as _ new SqlCommand( _ "SELECT pub_name,city,country FROM publishers "+_ "ORDER BY pub_name", _ objConnection ) ' Populate a reader. Dim objReader As SqlDataReader = objCommand.ExecuteReader() ' Set the DataList's data source and then ' call the DataBind() method. Publishers.DataSource = objReader Publishers.DataBind() ' Close the reader. objReader.Close() Catch ex As Exception ' Display the error message to the reader. ErrorMessage.Text = ex.Message.ToString() Finally ' See if the connection is open. If objConnection.State = ConnectionState.Open Then ' Close it if it is open. objConnection.Close() End If End Try End If End Sub As with the Page_Load() method for the Repeater demo, this code performs a pretty straightforward retrieval of data with which the Repeater is bound. Again, a connection to the database is created by creating a SqlConnection object and then calling its Open() method. And as per the recommended practice, the main code is within a try block. The try/catch/finally construct allows the code to be robust and handle any errors that might arise. If everything goes well, all of the code in the try block is executed, followed by the code in the finally block. If an exception is thrown at any point in the try block, execution proceeds to the catch block, after which the finally block will be executed. Once the connection has been established to the database, a SqlCommand object must be created. This gives us the capability to execute a query on the database and get a recordset back. The recordset will be contained in a SqlDataReader object. The following SQL will be executed: Select pub_name,city,country from publishers order by pub_name A call to the SqlCommand.ExecuteReader() method returns a populated SqlDataReader object. The Repeater is now bound to the data by setting the DataList.DataSource property to the SqlDataReader, and then calling the DataList.DataBind() method. The RedrawDataList_Click() Method Of the DataList DemoThe code for the RedrawDataList_Click() method follows. It is fired when users click the Redraw button. A discussion of the code is immediately below it. C#static Color[] color = { Color.Black, Color.Red, Color.Green, Color.Blue }; private void RedrawDataList_Click(object sender, System.EventArgs e) { // Loop through the items in the Publishers object (which is // a DataList). foreach( Control control in Publishers.Controls ) { // Make sure we have a line that's not a header or footer. if( ((DataListItem)control).ItemType == ListItemType.Item || ((DataListItem)control).ItemType == ListItemType.AlternatingItem ) { // Find the DropDownList object so that we know what // was selected. DropDownList dl = (DropDownList)control.FindControl( "StyleSelector"); Label Pub = (Label)control.FindControl( "pub" ); Pub.ForeColor = color[dl.SelectedIndex]; } } }VB Dim colr() As Color = {Color.Black, Color.Red, _ Color.Green, Color.Blue} Private Sub RedrawDataList_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles RedrawDataList.Click ' Loop through the items in the Publishers object (which is ' a DataList). Dim i As Integer For i = 0 To Publishers.Controls.Count - 1 Dim item As DataListItem = Publishers.Controls(i) ' Make sure we have a line that's not a header or footer. If item.ItemType = ListItemType.Item Or _ item.ItemType = ListItemType.AlternatingItem Then ' Find the DropDownList object so that we know what ' was selected. Dim dl As DropDownList = item.FindControl("StyleSelector") Dim Pub As Label = item.FindControl("pub") Pub.ForeColor = colr(dl.SelectedIndex) End If Next End Sub The code in the listings above is similar to the code in the Repeater demo that was fired in response to clicking the OK button. The first thing that you'll see in the listing, though, is an array of Color objects. These four objects are used to set the Label's color based on the DropDownList's index (more on this shortly). Next, you'll see the loops. In C#, a foreach loop is used; in VB, a For/Next loop is used. These loops go through each of the Control objects that are in the Publishers.Controls collection. A check is made to be sure that we're looking at either an ItemTemplate or an Alternating ItemTemplate. We don't want to inadvertently examine the HeaderTemplate. Once we're sure that we're looking at either an ItemTemplate or an AlternatingItemTemplate, we retrieve an object reference to the DropDownList object with the FindControl() method, as follows: C#DropDownList dl = (DropDownList)control.FindControl( "StyleSelector");VB Dim dl As DropDownList = item.FindControl("StyleSelector")
NOTE: Using the FindControl() method in C# and VB is different. For starters, the FindControl() method returns a generic Control object which could be one of many types of controls, such as Labels, DropDownLists, and TextBoxes. In VB, objects that are returned from the FindControl() method can easily be assigned to objects such as DropDownLists or Labels. VB does not check at compile time to see whether the object types match; it just assumes that you know what you're doing, and that the object types will match at runtime. But at runtime, if they differ, an exception will be thrown, and you'll have to deal with it at that time. In C#, however, the compiler checks to make sure the object types match. The following code will not compile: DropDownList dl = control.FindControl( "StyleSelector"); In this case, we have to coerce the compiler to continue and convince it we are sure that the object types will match. We use a typecast to let the compiler know that we are sure the object types will match. If, however, at runtime they don't match, an exception will be thrown, and you'll have to deal with it. The following code typecasts the previous C# example so that it compiles: DropDownList dl = (DropDownList)control.FindControl( "StyleSelector"); The next thing to do is retrieve an object reference to the Label. The following code shows how this is done: C#Label Pub = (Label)control.FindControl( "pub" );VB Dim Pub As Label = item.FindControl("pub") Last, the color of the Label is set to reflect the current selection. This is done by using the DropDownList.SelectedIndex as an index into the color (for C#) or colr (for VB) arrays (the reason for the name change is that VB is case insensitive and color will match the Color enumeration in VB). For instance, if Red is selected, then the DropDownList. SelectedIndex property will contain the value of 1. This will act as an index for the array containing the Color objects. The following breaks the code down: C#// Red is selected. This is the second choice, or an index value 1. // dl.SelectedIndex contains the value of 1. // color[1] contains the value Color.Red. // color[dl.SelectedIndex] also contains the value Color.Red // Pub.ForeColor = Color.Red is the result. Pub.ForeColor = color[dl.SelectedIndex];VB ' Red is selected. This is the second choice, or an index value 1. ' dl.SelectedIndex contains the value of 1. ' colr(1) contains the value Color.Red. ' colr(dl.SelectedIndex) also contains the value Color.Red ' Pub.ForeColor = Color.Red is the result. Pub.ForeColor = colr(dl.SelectedIndex) Figure 6.6 shows the DataList with different colors that have been selected. Figure 6.6. This DataList Renders with Different Colors. |