The Ins and Outs of the DataBind() Method

The Ins and Outs of the DataBind() Method

The DataBind() method is a method defined in the System.Web.UIControl class. All ASP.NET Web and HTML controls (including the data Web controls) are derived from this base class, so all controls support a DataBind() method. However, this method is virtual, meaning it contains no defined body, and it's up to the derived classes that want to use the functionality to override the method name, associating some action with the method call.

Most controls do not override the default DataBind() method, so calling DataBind() on most controls, such as the TextBox control, has no effect. The important controls that have overridden the DataBind() method are the Page class, the list Web controls (DropDownList, ListBox, RadioButtonList, and CheckBoxList), and the data Web controls.

NOTE

Every ASP.NET Web page, when first visited, is converted into a class that is derived from the Page class. If you use code-behind pages, you are likely aware that the code-behind class inherits the Page class.

Essentially, the Page class contains properties, methods, and events that abstractly define an ASP.NET Web page. In the HTML section of an ASP.NET Web page you can use data-binding syntax referencing a variable, expression, or method call. For example, you could use data binding to emit the current date and time like this:

 <%# DateTime.Now %> 

To have the data-binding syntax dynamically rendered, you'd need to ensure that you call Page.DataBind() somewhere in your code section.

Although data binding at the page level is worth investigating, this book is neither the time nor the place for such a study. Instead, we will focus on data binding at the data Web control level. For more information on data binding at the page level, refer to the resources in the "On the Web" section.


It's important to note that when a control's DataBind() method is called, the call is cascaded through the control's child controls. That is, if you call the DataList's DataBind() method, the DataBind() method is also called on the HeaderTemplate, FooterTemplate, ItemTemplate, and whatever other templates might be defined for the DataList.

The First Steps of the DataBind() Method Call

When the DataBind() method is called, the following sequence of events occur (note that some of the finer details have been omitted, focusing instead on the germane details):

First, the object specified by the DataSource property is enumerated. Recall that the DataSource must implement the IEnumerable interface, so we know with certainty that we'll be able to enumerate over whatever object has been assigned to the DataSource property.

At each step in the enumeration, an appropriate Item object is created. If the data Web control being used is a DataGrid, a DataGridItem object is created; for the DataList, a DataListItem is created; and for the Repeater, a RepeaterItem is created. Each of these objects has an ItemType property that indicates whether the row being added is a standard Item, an AlternatingItem (every even row), the SelectedItem (the item that has been selected), an EditItem (the item currently being edited), a Header, a Footer, and so on. (We'll be discussing these item types in future chapters.)

NOTE

The DataGridItem, DataListItem, and RepeaterItem are classes in the System.Web.UI.WebControls namespace that abstractly define an item in the DataGrid, DataList, and Repeater Web controls, respectively.

At this point, the paths of the various data Web controls diverge a bit. Therefore, let us examine the path each data Web control takes separately.


Completing the DataBind() Method Call for the DataGrid

The DataGridItem class is derived from the TableRow class. This isn't surprising, because for each row in the DataSource, an HTML table row is rendered.

Let's focus specifically on the DataGrid for a moment. For each column in the current item of the DataSource, a TableCell object is created. If the AutoGenerateColumns property is set to True, the Text property of the TableCell is set equal to the value of the associated column in the current item of the DataSource. If AutoGenerateColumns is set to False, a different action is taken, depending on the control specified in the Columns tag. If a BoundColumn is used, then, as with AutoGenerateColumns set to True, the value of the column is placed in the Text property. If a HyperLinkColumn is used, a HyperLink Web control is added as a child of the TableCell object.

Completing the DataBind() Method Call for the DataList

Turning our attention to the DataList, we find that the DataListItem is derived from the WebControl class. At first, one might assume that the DataListItem would be derived from the TableRow, just like the DataGridItem. However, recall that each "row" in the DataSource does not necessarily correspond to an HTML table row. In fact, this is only the case when the RepeatColumns property equals 1 (the default). When RepeatColumns is set to a value of n (n greater than 1), then there are n "rows" from the DataSource per HTML table row.

Recall that the DataList's rendering is determined by the templates it specifies, and that the DataList can support a multitude of template types, such as the ItemTemplate, AlternatingItemTemplate, EditItemTemplate, and so on. These templates are defined as properties of the DataList class, which includes classes that implement the ITemplate interface. A class implementing the ITemplate interface need only have one method: InstantiateIn(container ), where container is an object of type Control. Essentially, the InstantiateIn() method turns the template into a series of child controls, whose parent control is the control specified by container .

You'll remember that at this point the DataList's DataSource is being enumerated through, and for each item in the DataSource, a DataListItem object is created. Next, the appropriate template's InstantiateIn() method is called, passing in the DataListItem object as the parameter to the InstantiateIn() call. This has the effect of implementing the contents of the template as child controls of the DataListItem object. (If you're wondering what the "appropriate template" in the second sentence refers to, remember that what template we use depends on the ItemType of the DataListItem. That is, if the current DataListItem is an AlternatingItem, we want to use the AlternatingItemTemplate, if it exists.)

At this point, the current item of the DataSource being enumerated over is assigned to the DataItem property of the DataListItem. (Note that both the DataGridItem and RepeaterItem have a DataItem property as well.) The DataBind() method of the DataListItem is then called. This has the effect of resolving any data binding syntax that might have appeared in the template that was attached to the DataListItem.

This concludes the steps needed to be taken to display a particular field from the DataSource in the data Web control. Of course, this process must be repeated for each item in the DataSource.

Recall that Listings 2.2 and 2.3 had some data-binding syntax in the ItemTemplates that we had not seen before. Take a moment to look back at these code listings, paying attention to the ItemTemplates in both examples. In Listing 2.2, the DataSource was set to an array of strings. This means that when the DataSource is being enumerated over, each item is of type string. Hence, in our ItemTemplate for Listing 2.2 (line 15) we simply have

 <%# Container.DataItem %>. 

Why does Container.DataItem render the file name? Recall that the DataListItem has a property named DataItem, which was assigned the value of the current DataSource item. The reason we have to predicate it with Container is because the data-binding syntax appears in the template, which is instantiated as a child control of the DataListItem. Hence, we are not referring to the template object, but to its container, the DataListItem object.

Because the DataSource in Listing 2.2 is a string array, each DataItem is a string. Therefore, our data-binding syntax is complete with just Container.DataItem.

NOTE

The type returned by data-binding syntax (<%# ... %>) depends on the context with which the data-binding syntax is used. For now, we'll just concentrate on having the data-binding syntax return string values. This is an appropriate return type for the types of data binding we've been using thus far; we're simply using data binding to emit a dynamic string into an HTML table cell.

As we will see in the next chapter, we can use data binding to return a plethora of different types, thereby allowing us to dynamically assign values to various properties via data-binding syntax.


In Listing 2.3, our data-binding syntax was a bit more hairy. Recall that here the DataSource was specified as a Hashtable. The ItemTemplate (lines 30 and 31) contains the following HTML markup and data-binding syntax:

 <li><%# DataBinder.Eval(Container.DataItem, "Key") %> - <%# DataBinder.Eval(Container.DataItem, "Value") %></li> 

When a Hashtable is enumerated over, each item returned is a DictionaryEntry structure. The DictionaryEntry structure contains two properties: Key and Value, which correspond to the key and value of the particular Hashtable entry. Because the DataSource in Listing 2.3 is a Hashtable, each DataItem is a DictionaryEntry. Because our data-binding syntax must return a type of string, if we just use <%# Container.DataItem %> as we did in Listing 2.2, the output will be the result of the ToString() method call of the DictionaryEntry structure, resulting in an output of

 "System.Collections.DictionaryEntry." 

Because we want to display the key and value, we need to return those properties from the DataItem object. One might think this would be as easy as using <%# Container.DataItem.Key%> and <%# Container.DataItem.Value %>. However, this will not work, because the DataItem property is defined as an instance of the Object class, which has no properties, and only a handful of very generic methods (Equals(object ), GetType(), ToString(), and so on). That is, DataItem has no way of knowing that it is actually a DictionaryEntry object.

To circumvent this problem, we must use the DataBinder.Eval method. The DataBinder.Eval() can accept either two or three parameters. In the two-parameter version, it takes an object and a string as input. It then determines, via reflection, whether object.string is a legal call; if it is, it performs it. Hence, to grab the value of the Key property from the current DictionaryEntry object, we use

 <%# DataBinder.Eval(Container.DataItem, "Key") %> 

and to obtain the value of the Value property from the current DictionaryEntry object, we use

 <%# DataBinder.Eval(Container.DataItem, "Value") %> 

Note that

 DataBinder.Eval(Container.DataItem, "Key") 

and

 DataBinder.Eval(Container, "DataItem.Key") 

are equivalent, because in the end both resolve down to checking whether Container.DataItem.Key is a valid call.

NOTE

When programming with .NET, all objects contain metadata that describe the object, its type, its properties, events, methods, and so on. Reflection is the process of inspecting this metadata to determine such high-level information about an object at run-time. For more information on reflection, check out the System.Reflection namespace, or view the suggested link in the "On the Web" section at the end of this chapter.


Applying Style Information for the DataGrid and DataList

Realize that both the DataGrid and DataList Web controls contain a number of properties to specify stylistic information. These properties include those that apply to the entire control, like BackColor, ForeColor, and Font, and those that apply specifically to each item or alternating item, such as ItemStyle and AlternatingItemStyle.

We'll examine these various properties and how to use them to make your DataGrid and DataList's output more aesthetically pleasing in Chapter 3, "Customizing the HTML Output." For now, though, understand that these styles are applied at different times during the DataBind() call. For example, the styles that apply to an HTML table row, such as the ItemStyle, are applied to the DataGridItem and DataListItem controls.

Note that the Repeater control does not support any style properties. With the Repeater, such style information must be explicitly coded into the HTML markup in the various templates.

Completing the DataBind() Method Call for the Repeater

To complete our examination of the DataBind() method call, we must examine what occurs with the Repeater control once the DataSource is being enumerated. Not surprisingly, the series of steps the Repeater takes is nearly identical to that taken by the DataList. But there are some subtle differences: rather than DataListItems being created, RepeaterItems are created instead. Regarding the Repeater's templates, the same series of steps are taken as with the DataList.

Now that we've examined what happens to the various data Web controls when the DataBind() method is called, let's return to a topic we touched upon earlier in this chapter: creating our own class that implements the IEnumerable interface and using it as the DataSource for a data Web control.



ASP. NET Data Web Controls Kick Start
ASP.NET Data Web Controls Kick Start
ISBN: 0672325012
EAN: 2147483647
Year: 2002
Pages: 111

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net