Other Data-binding Properties
The
DataSource property references the global data source object bound to the control. In general, a few more properties are required to select particular columns of data out of the source. How many, and which, columns depends on the characteristics of the control. For example, the built-in DropDownList control features two additional properties:
DataTextField and
DataValueField. The former indicates the data source column to be used as the display text of each listed item. The latter indicates the data source column that provides the underlying values for the items. For example, take a look at the HTML snippet below that renders a drop-down list.
<select>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
The body of each
<option> tag contains the display text; the value attribute of the tag contains a likely unique value to identify the element. The ASP.NET DropDownList control just uses
DataTextField and
DataValueField properties to bind distinct columns of the data source to the text and value of each
<option> tag being generated.
You can apply a similar pattern to virtually any data-bound control. For example, hyperlink columns of a DataGrid feature a
DataNavigateUrlField property to let you bind a data source property to the URL of the hyperlink.
The BarChart control here needs a couple of properties to data-bind the label and value of each rendered bar. You can choose any name for these properties; I stuck to classic
DataTextField for the bar label and
DataValueField for the bar value. Here's the implementation of
DataTextField.
private void Form1_Load(object sender, _
System.EventArgs e)
{
public string DataTextField
{
get
{
object o = ViewState["DataTextField"];
if (o == null)
return "";
return (string) o;
}
set {ViewState["DataTextField"] = value;}
}
}
The
DataValueField is nearly identicaljust change the property name and you have it. The content of the property is saved to and read from the page's ViewState. Note the convention used to assign a default value to a property in the
get accessor.
The value of the property is first read out of the ViewState and assigned to an object. If the reference is null, you return what's expected to be the default value of the property. If the reference is not null, you cast it to the right type and return. Properties of built-in ASP.NET controls are coded in this way. There's no need to initialize properties in the class constructor.
To make the control more complete, I've also added a couple of extra string properties to add formatting to both the label text and value. The properties are named
DataTextFormatString and
DataValueFormatString. Their implementation closely reflects the code snippet above.
The Items Property
In a data-bound control, the
Items property can have a double goal. In simple list controls such as DropDownList and ListBox, the
Items property returns a reference to the list of items that are currently stored in the control. With this reference, you can add items, remove items, and obtain a count of the items in the collection. Put another way, the
Items collection is an alternative data source that can be used along with the contents of the
DataSource property. You can populate a ListBox with the following code, for instance.
for (int i = 1; i <= 50; i++)
{
list.Items.Add("Item " + i.ToString());
}
More complex data-bound controls, such as the DataList, assign a different role to the
Items property. The property gets a collection of objects representing the individual items within the control. The exact configuration of this object depends on the control. For the DataList, an item is an instance of the HTML template used to render a data-bound itemmostly a table row. For the BarChart control, the Items property returns a custom collection, as shown below.
[Browsable(false)]
public virtual BarChartItemCollection Items
{
get
{
if (_items == null)
_items = new BarChartItemCollection();
return _items;
}
}
The source code of the BarChartItemCollection class is presented in
Listing 1.
If you look back at
Figure 1, you should grasp what items are here pretty easily. An item is a row in the table output by the BarChart control. The row contains a couple of cellslabel and graphical representation of the bar. Just because an item here is a table row, the BarChartItem class (
Listing 1) inherits from TableRow.
A BarChartItem object is simply an enhanced version of a table row, extended to contain item type and data item properties.
ItemType indicates the type of the item in the context of the BarChart controlbe it the title row, the subtitle row, a data row, or perhaps the footer.
DataItem references the n'th data object in the enumerable collection bound to the control. If you're only a little bit familiar with DataList or DataGrid internals, this approach should be nothing new. Classes like DataGridItem and DataListItem are implemented in a similar manner.
All data-bound controls of some complexity expose the internal collection of items as a way to ease developers with any required customization. Internally, the collection of constituent items helps immensely with the rendering of the control, as you'll see in a moment.
An important thing to keep in mind about the
Items property is that, as implemented here, it doesn't represent an extension to the data source. You can't add data to the control through this property. The
Items property is read-only in the sense that page developers can't assign or replace it with another collection. However, you can add or remove items to the collection as long as the underlying collection class permits that. Finally, the name of the property is totally arbitrary. Likewise, your control can have as many similar collections as needed.
In the BarChart control, the
Items collection is populated during the data binding step and consumed at rendering time.
As the code snippet above shows, the
Items collection is not saved to the ViewState. I'll return to this later, as it is a critical point for the behavior of complex and composite data-bound controls.