The .NET Framework includes a number of databound controls. These controls allow you to use data from a data source to easily populate the control. The data source can be any of a number of different types of objects, depending upon the control. Here is a list of the controls that are considered databound controls.
These controls are considered databound because a DataSet, a Data Reader, or an Array can be assigned to a control and then bound. Normally this is done by setting the DataSource property to the collection of data that you want to bind to, and then calling the DataBind() method.
ListBox, DropDownList, RadioButtonList, and CheckBoxList
The simplest of the databound controls are the list controls. These controls are all identical in terms of how they are used because the data binding is implemented in a common base class called ListControl. Using these controls is quite simple; just do the following:
Here is an example of how to do this. Our data will be a list of country names and country codes. For the example I'm assuming that we have a DataReader already set up. It will have two columns, Country and Country Code. This data will be loaded into a DropDownList.
The .aspx code looks like this:
<asp:DropDownList style="Z-INDEX: 101; LEFT: 88px; POSITION: absolute; TOP: 152px" runat="server" DataTextField="Country" DataValueField="CountryCode"> </asp:DropDownList>
The code to initialize the data in the Page_Load event handler looks like this:
Dim objConnection As New SqlConnection 'Setup and Open Connection Here Dim objCommand As New SqlCommand Dim objReader As SqlDataReader objCommand.CommandText = _ "SELECT Country,CountryCode FROM tblCountryList" objCommand.Connection = objConnection objCommand.ExecuteReader(CommandBehavior.CloseConnection) Me.CountryList.DataSource = objReader Me.DataBind()
It is important to note that the reader will be closed by the DataBind() method. You can't perform additional queries on a connection with an opened reader. If you call the ExecuteReader with the CommandBehavior.CloseConnection parameter, the connection will be automatically closed when the reader is closed. If you do not call ExecuteReader with this parameter, you will need to be sure and close the connection manually.
The Repeater Control
The Repeater control is the most basic of the iterative databound controls. This has its advantages and disadvantages. The advantage is that the Repeater control does not have an inherent look. There is no default layout or display methodology. This makes is possible for you to do whatever you want with it. The disadvantage is that it takes more work to do something simple.
The Repeater control uses templates to define how things are displayed. Each template is used to define different portions of the Repeater control's data. Here is a list of the templates used by the repeater controls and what the template is used for:
When the Repeater control renders itself, it starts by rendering the HeaderTemplate, followed by an ItemTemplate alternating with the AlternatingItemTemplate if it is defined for each data row to be rendered. The Repeater control renders a SeparatorTemplate between each of the ItemTemplate or AlternatingItemTemplate data. Finally, the FooterTemplate is rendered.
The Repeater must be bound to a data source prior to using it. If it is not bound to a data source, nothing will be rendered. Data is bound to the Repeater control by assigning a data source to the DataSource property and then calling the DataBind() method. Any class that implements the ICollection or the IEnumerable interfaces can be used as a data source. Common data sources include the DataTable class and the SqlDataReader class. Other classes such as the Array class or the ArrayList class can also be used as a data source.
The Repeater control supports three Repeater-specific events: the ItemCreated event, the ItemDataBound event, and the ItemCommand event. The ItemCreated event is fired after the contents of the ItemTemplate are created, but before they are databound. This event should be handled if you want to make changes to the controls inside the ItemTemplate that don't rely on the data in the template.
The ItemDataBound is fired after the data binding is done but before the item is rendered on the page. This event should be handled if you need to make changes based on the data being bound. This would include things such as changing the style of the displayed text based upon what text is being displayed, or changing a label control to a link control if the text being bound to it is a URL.
The ItemCommand event is fired if any of the contained controls fire a Command event. This allows you to handle events from things such as buttons without specifically attaching an event handler to every item that is rendered.
Let's look at an example. The example will be taken from the contact portion of the scheduling application where an alphabet list is provided to filter the contacts alphabetically.
Here is the .aspx code to define the repeater:
<asp:Repeater runat="server" EnableViewState="False"> <ItemTemplate> <td> <asp:LinkButton Runat="server" CommandName="CHANGE" CommandArgument=' <%# DataBinder.Eval(Container.DataItem, "Name") %>'> <%# DataBinder.Eval(Container.DataItem, "Name") %> </asp:LinkButton></td> </ItemTemplate> </asp:Repeater>
The following code behind code is called to load the data in to the Reader.
Listing 5.1 The CountItem Class
' This class counts the items in a control. Private Class CountItem Public Sub New(ByVal strName As String, ByVal nValue As Integer) m_Name = strName m_Value = nValue End Sub ' Private variables Private m_Name As String Private _Value As Integer Public ReadOnly Property Name() Get Return m_Name End Get End Property Public ReadOnly Property Value() Get Return m_Value End Get End Property Private Sub LoadAlphaList() Dim objCounts() As CountItem Dim I As Integer Dim isValidReader As Boolean Dim objReader As IDataReader Dim strName As String objCounts = Array.CreateInstance(GetType(CountItem), 27) objCounts(0) = New CountItem("All - ", _ Page.AuthUser.ContactCount) objReader = Page.AuthUser.ContactAlphaCountsReader isValidReader = objReader.Read() For I = 1 To 26 strName = Chr(Asc("A") + I - 1) If isValidReader Then ' AlphaInx is the column with the X increment. If objReader.Item("AlphaInx") = I Then ' ContactCount is the column that counts the contacts. objCounts(I) = New CountItem(strName, _ objReader.Item("ContactCount")) isValidReader = objReader.Read() Else objCounts(I) = New CountItem(strName, 0) End If Else objCounts(I) = New CountItem(strName, 0) End If Next objReader.Close() Me.ctlAlphaList.DataSource = objCounts Me.ctlAlphaList.DataBind() End Sub End Class
In this case, the data is first loaded into an array of custom objects. The array is the set to be the Repeater's data source.
The DataList control is a flexible control for displaying information from a DataSource. Like the Repeater control, it does not force you to use a given structure for displaying your data, but it allows more flexibility because you can specify different templates for selected items and for items that are being edited. With the DataList control, you can also specify styles to be applied to any of the templates.
If you don't wish to specify your own structure, you can set the RepeatLayout property to RepeatLayout.Table to display the data in a table. If you choose to use the table layout provided by the DataList control, it is assumed that each item is to be rendered in a single cell of the table, which means your table will have only a single column or row, depending upon the setting of the RepeatDirection property. If your data item is actually a row from a data source with multiple data fields, you will need to specify your own layout rather then using the built-in table layout if you wish each field in the row to be displayed in its own cell.
The DataList control uses templates to define how it is displayed. Each template is used to define different portions of the DataList control's data. Here is a list of the templates used by the repeater controls and what each template is used for:
When the DataList control renders itself, it starts by rendering the HeaderTemplate, followed by an ItemTemplate alternating with the AlternatingItemTemplate if it is defined for each data row to be rendered. The Repeater control renders a SeparatorTemplate between each of the ItemTemplate or AlternatingItemTemplate data. Finally the Footer Template is rendered. If an item is being edited, then the EditItem Template will be rendered instead of the ItemTemplate. If an item is selected, then the SelectedItemTemplate will be rendered instead of the ItemTemplate.
One of the big advantages of the DataList control over the Repeater control is the capability to set styles that match each of the templates. These styles are not rendered specifically on the matching template but are rendered where the template would be used if it existed. This allows you to do things such as specify alternating background colors without specifying an Alternating ItemTemplate. Here is a list of the style properties that can be defined:
Like the Repeater control, the DataList control must be bound to a data source prior to using it. If it is not bound to a data source, nothing will be rendered. Data is bound to the DataList control by assigning a data source to the DataSource property and then calling the DataBind() method. Any class that implements the IEnumerable interface can be used as a data source. This means that common data sources such as the DataTable class and the SqlDataReader class, as well as other classes such as the Array class or the ArrayList class, can be used as data sources.
The DataList control has a number of events that can be handled. These events allow you to customize the DataList control in a variety of situations.