Browse DevX
Sign up for e-mail newsletters from DevX


A Crash Course on Custom ASP.NET Data-bound Controls : Page 4

Data-bound controls require a data source property and a set of string properties that link to particular columns of the data source. In addition, they need an Items collection property to track all the building blocks of the control's user interface. Finally, a well-done data-bound control supports styles and custom events.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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 identical—just 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 item—mostly 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 cells—label 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 control—be 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.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date