Simplified and Extended Data Binding Syntax in ASP.NET 2.0

©2004 Stonebroom Limited, England. By Alex Homer, alex@stonebroom.com

 

The server-side data binding techniques that were introduced in ASP.NET version 1.0 revolutionized the way developers build pages that access data. No longer was there a requirement for complex and lengthy code sections that build up HTML tables or lists of values. However, using ASP.NET 1.x, you still have to write code to perform the data access and expose the data to the list or grid controls for data binding.

 

In version 2.0, new data source controls can be used to remove the need for any code at all, while still providing a whole range of features for extracting data that can be filtered, sorted and paged for display. They also support automatic updates to data for the new GridView, DetailsView and FormView controls, making it extremely easy to build data access pages with little or no server-side code being required.

 

To support these features, there have been both simplifications and extensions to the syntax used for data binding. The syntax used in version 1.x can be confusing, cumbersome, and is tedious and to write. In version 2.0, data binding statements are more concise, easier to use, and reduce complexity (of course, the existing version 1.x syntax is still supported). Plus, for hyperlinks in the new GridView control, you can now specify more than one column or expression for binding to the control; allowing more than one value to be used when constructing the URL (href) attribute of the resulting hyperlink.

 

And, more that this, there are three new types of data binding statement you can use. OK, it may seem that this makes nonsense of the simplifications just described, but in fact these additions provide broader opportunities for data binding. There are two new expressions aimed at supporting XML data with the new data source controls added to version 2.0 of ASP.NET. There is also a new expression to provide 2-way data binding in controls that support no-code automatic updating of the source data.

 

So, this article looks at:

 

  • The simplification of, and extensions to, the ASP.NET 1.x data binding syntax
  • The new two-way data binding syntax for updating data sources
  • The new syntax for binding to XML data in ASP.NET 2.0

 

The Simplified Data Binding Syntax in ASP.NET 2.0

Many developers have questioned the verbose and seemingly inflexible nature of the statements that are required to perform data binding to ASP.NET list controls such as the Repeater, DataList and DataGrid. Plus, when writing pages in C#, it's not unknown for data type conversion issues to arise, because C# does not perform the same level of implicit data type conversion as Visual Basic .NET.

 

The Existing Data Binding Syntax in ASP.NET 1.x

In it's simplest form, the format for data binding in ASP.NET 1.x is:

 

<%# Container.DataItem("expression") %>

 

In a list control, expression is usually the column name. For example, this code inserts the value from the CustomerName column in the current row into a Label control (notice the use of single quotes to enclose the data binding statement, which itself contains double quotes):

 

<asp:Label id="label1" runat="server"

     Text='<%# Container.DataItem("CustomerName") %>'

 

However, any valid expression that returns a value can be used in a data binding statement. And the same syntax can, of course, be used outside list controls. For example, it can be used to display a value directly in the page, or as the value of an attribute for any other server control.

 

The limitation with this simple syntax is that values cannot be formatted. Instead, you must use the Eval method of the object that is exposing the data, referenced through the static DataBinder object. This method has two overloads, one of which takes an additional parameter that specifies the formatting to be applied to the value:

 

<%# DataBinder.Eval(Container.DataItem, "expression"[, "format"]) %>

 

The format parameter is a String value, using the value placeholder replacement syntax (called composite formatting) like his:

 

<asp:Label id="label1" runat="server"

     Text='<%# DataBinder.Eval(Container.DataItem, "OrderDate",  _

                                         "{0:dddd d MMMM"]) %>'

 

The placeholder is always zero in ASP.NET 1.x, and the format string following the colon can be one of the predefined characters (such as C for currency, or t for the short version of the time), or a custom format string made up of a combination of text and formatting characters. The format string "{0:dddd d MMM}" shown in the code above produces output of the form: Monday 24 May.

For details of the characters and syntax used in formatting strings, see:

http://msdn.microsoft.com/library/en-us/cpguide/html/cpconformattingoverview.asp

For details of the composite formatting syntax, see:

http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcompositeformatting.asp

Data Binding Statements in ASP.NET 2.0

One of the reasons that the two different approaches to the data binding syntax were originally made available is that using the Container object is more efficient at runtime than the Eval method of the DataBinder object. This is because the Eval method uses late-bound reflection to determine the value type. However, this difference is marginal in almost all cases.

 

In ASP.NET 2.0, you should generally use the Eval method. And, to make this easier, the DataBinder object that exposes it has been made the default context for all non-hierarchical (rows and columns) data binding expressions. This means that you can use a much simpler syntax. If you just want to display a value without formatting it, use the Eval method directly:

 

<%# Eval("expression") %>

 

Or, if you need to format the value, use the second overload that accepts a format string:

 

<%# Eval("expression"[, "format"]) %>

 

The format parameter works here just like it does in v1.x. So, for example, you can format the value in a column named Price as currency using:

 

<%# Eval("Price", "{0:C}") %>

 

And, as in v1.x, you can use more complex format strings to display text as well as the current row value:

 

<%# Eval("Price", "Special Offer {0:C} for Today Only!") %>

Using Multiple Data Bound Values in a Hyperlink Control

Another area where ASP.NET 2.0 extends the data binding syntax of v1.x is when you use a HyperLinkField in the new GridView or DetailsView controls. We don't have room to cover these controls in detail here, though any developer who has to display hierarchical data will no doubt have already headed straight for these great new controls and experimented with their capabilities. They can be used in conjunction with the new data source controls to provide "no-code required" display of data from almost any data source. For example, this is all you need to display the contents of the Products table in the sample Northwind database in SQL Server:

 

<form runat="server">

 

<asp:SqlDataSource id="datasource1" runat="server"

     ConnectionString="server=localhost;database=Northwind;uid=x;pwd=y"

     SelectCommand="SELECT ProductID, ProductName, QuantityPerUnit,

                    UnitPrice, UnitsInStock, Discontinued FROM Products"

/>

 

<asp:GridView id="gridview1" DataSourceID="datasource1" runat="server" />

 

</form>

 

The screenshot below shows the results. This example, basic-binding.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.

 

 

However, the new data binding capability comes to light once you turn off automatic column generation by adding the attribute AutoGenerateColumns="False" to the declaration of a GridView control, or AutoGenerateRows="False" to the declaration of a DetailsView control. You can then declare a HyperLinkField control within the <Columns> section of the GridView control, or within the <Rows> section of the DetailsView control.

The DataNavigateUrlFields Property

The new HyperLinkField control exposes a property named DataNavigateUrlFields, which is broadly equivalent to the DataNavigateUrlField property of the HyperLinkColumn you would use in a DataGrid control in v1.x. But, as the name suggests, it accepts more than one column name or expression. In the control declaration, you specify the column names as a comma-delimited list, for example:

 

DataNavigateUrlFields="ProductID,SupplierID,ProductType"

 

There is also a DataNavigateUrlFormatString property exposed by the HyperLinkField control - just like the HyperLinkColumn control in version 1.x. The useful feature with the HyperLinkField control is that you can now take advantage of ability of the DataNavigateUrlFields property to bind to multiple columns, and insert more than one value from the current row into the NavigateUrl (the href attribute) of the resulting hyperlink.

 

As an example, the code below uses feature to provide a hyperlink that contains two values, both extracted from the current row of the Customers table, for the href attribute:

 

<asp:SqlDataSource id="datasource1" runat="server"

     SelectCommand="SELECT CustomerID, CompanyName, City FROM Customers"

/>

 

<asp:GridView id="gridview1" DataSourceID="datasource1" runat="server"

              AutoGenerateColumns="False">

  <Columns>

 

    <asp:BoundField DataField="CustomerID" HeaderText="BoundField" />

 

    <asp:HyperLinkField runat="server"

         DataTextField="CustomerName"

         DataNavigateUrlFields="CustomerID,City"

         DataNavigateUrlFormatString=

           "http://yoursite.com/showcustomer.aspx?id={0}&city={1}" />

 

  </Columns>

</asp:GridView>

 

The resulting value for the href attribute will be something like this:

 

"http://yoursite.com/showcustomer.aspx?id=ALFKI&city=Berlin"

 

The screenshot below shows the results. This example, hyperlinkfield.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.

 

Setting the DataNavigateUrlFields Property at Runtime

You can also set the DataNavigateUrlFields and DataNavigateUrlFormatString properties at runtime using code. To set the DataNavigateUrlFields property you must create a String array and assign it to the DataNavigateUrlFields property during the Load event of the parent GridView or DetailsView control:

 

' event handler specified in the OnLoad attribute of the control

Sub GridView1_Load(ByVal sender As Object, ByVal e As EventArgs)

 

  ' create and populate the array of column names

  Dim aFields(1) As String

  aFields(0) = "CustomerID"

  aFields(1) = "City"

 

  ' get reference to the column as a HyperLinkField control instance

  ' specify the index of the column within the Columns collection

  Dim oHLField As HyperLinkField = CType(sender.Columns(1), HyperLinkField)

 

  ' set the DataNavigateUrlFields property

  oHLField.DataNavigateUrlFields = aFields

  oHLField.DataNavigateUrlFormatString = _

           "http://yoursite.com/showcustomer.aspx?id={0}&city={1}"

End Sub

 

The code above is in Visual Basic .NET. The equivalent in C# is shown below. Notice that the control name (GridView1) is referenced directly, because the sender parameter is of type Object and cannot be implicitly converted to a GridView type (and, hence, does not have a Columns collection):

 

void GridView1_Load(object sender, EventArgs e) {

  String[] aFields = new String[2];

  aFields[0] = "CustomerID";

  aFields[1] = "City";

  HyperLinkField oHLField = (HyperLinkField) GridView1.Columns[1];

  oHLField.DataNavigateUrlFields = aFields;

  oHLField.DataNavigateUrlFormatString =

           "http://yoursite.com/showcustomer.aspx?id={0}&city={1}"

}

The New Two-Way Data Binding Syntax

When building pages that use list or grid controls in ASP.NET 2.0, the new data source controls make it much easier than the v1.x approach of using code in the page to generate a DataReader or DataSet instance, and then binding this to the control. In version 2.0, you simply place a data source control on the page, and link it to the list or grid control using the DataSourceID attribute of property of the control. You saw an example of this in the earlier section "Using Multiple Data Bound Values in a Hyperlink Control".

 

This approach can be used with any of the list controls that are provided with ASP.NET 2.0, including those that were originally introduced in version 1.0 (for example, the DataGrid, DataList, Repeater, ListBox, and HtmlSelect controls). However, data source controls really come into their own when used with the new GridView, DetailsView and FormView controls.

Automatic Updates with the New Data Source Controls

The original version 1.0 list and grid controls are effectively "read-only", in that you have to write code that is executed in response to events raised by controls within the list or grid (for example, when the user clicks an Update or Delete link). This code must collect the values in the relevant row and then execute some code you've written to push these values back into the data store - possibly using stored procedures or explicit SQL statements. In other words, data binding is only being used to populate the list or grid control.

 

In the GridView, DetailsView and FormView controls, this is no longer the case. As long as the data source is updateable, and you have provided the appropriate update, insert and delete commands, the control will automatically push changes to the values in the list or grid control to which it's attached back into the data source. You can specify the update, insert and delete commands as explicit SQL statements, or use stored procedures if you need to interact with a more complex database table structure.

 

What's important with respect to the topic of this article, however, is how these new controls affect the syntax used for data binding. When the columns or rows for a GridView or DetailsView control are auto-generated, or specified using a the pre-defined field types such as BoundField, HyperLinkField, or CheckBoxField, the data source control can figure out what to do when it's time to push changes back into the data store by looking at which columns each of the field types is bound to.

 

But, if you use a TemplateField in a GridView or a DetailsView, you must declare all the content for that column or row yourself, just as you would when using a TemplateColumn in a DataGrid control. And, if you use a FormView control, you always have to declare all the content yourself. Like the v1.0 Repeater control, the FormView control does not support pre-defined column types - it uses only templates for content generation.

 

Inside the templates of a TemplateField, or in the templates of a FormView control, you use data binding statements to connect the controls you declare there with the columns in the data source control. The interesting point is that the data binding technology must, in this case, support both "read" and "write" operations, rather than being "read-only" as has always been the case in the past. This is termed two-way data binding, and is supported through a new method called Bind.

The Bind Method

As with the Eval method, the Bind method has two overloads, which means that it can be used with or without the "format" parameter:

 

<%# Bind("expression"[, "format"]) %>

 

In fact, other than specifying the new method name, the Bind method is used just like the Eval method. To bind an attribute of a control to the CompanyName column, you use:

 

<%# Bind("CompanyName") %>

 

If you want to bind an attribute of a control to a value that requires formatting, you add the format parameter:

 

<%# Bind("OrderDate", "{0:dddd d MMMM}") %>

 

To demonstrate the Bind method, the following code shows a SqlDataSource control with parameterized SQL statements specified for the UpdateCommand and InsertCommand property attributes. The data source control exposes a two-column rowset containing the ID and name of products from the SQL Server Northwind sample database:

 

<asp:SqlDataSource id="datasource1" runat="server"

     SelectCommand="SELECT ProductID, ProductName FROM Products"

     UpdateCommand="UPDATE Products SET ProductName=@ProductName

                    WHERE ProductID=@ProductID"

     InsertCommand="INSERT INTO Products (ProductName)

                    VALUES (@ProductName)"

/>

 

The next listing shows how the templates of a FormView control can be declared to allow the product name to be edited or a new product to be added. For this to work, the FormView control must know which is the primary key column in the source data, and this is declared using the DataKeyNames attribute (multiple column primary keys are specified using a comma-delimited list of column names in the control declaration, or a String array of column names at runtime).

 

<asp:FormView id="formview1" DataSourceID="datasource1" runat="server"

              DataKeyNames="ProductID" AllowPaging="True">

 

  <ItemTemplate>

    <b><%#Eval("ProductName")%></b><p />

    <asp:LinkButton id="btnEdit" runat="server"

         CommandName="Edit" Text="Edit Details" /><br />

    <asp:LinkButton id="btnInsert" runat="server"

         CommandName="New" Text="Add New Product" />

  </ItemTemplate>

 

  <EditItemTemplate>

    <asp:Label id="lblEditID" runat="server"

         Text='<%# Bind("ProductID")%>' />

    <asp:TextBox id="txtEditName" runat="server"

         Text='<%# Bind("ProductName") %>' />

    <asp:LinkButton id="btnUpdate" CommandName="Update"

         Text="Update" runat="server" />

    <asp:LinkButton id="btnCancel" CommandName="Cancel"

         Text="Cancel" runat="server" />

  </EditItemTemplate>

 

  <InsertItemTemplate>

    <asp:TextBox id="txtInsertName" runat="server"

         Text='<%# Bind("ProductName") %>' />

    <asp:LinkButton id="btnAdd" CommandName="Insert"

         Text="Add" runat="server" />

    <asp:LinkButton id="btnAbandon" CommandName="Cancel"

         Text="Cancel" runat="server" />

  </InsertItemTemplate>

 

</asp:FormView>

 

Then each template section declares a control to either display or allow editing of the product name. In the ItemTemplate, where the value is just being displayed, the code can use the Eval method to bind to the ProductName column. In the EditItemTemplate and the InsertItemTemplate, the product name is displayed in a TextBox control, allowing it to be edited or entered. Because we want to push these values back into the database, the Bind method must be used here.

 

One important point to note is that the ProductID column is the primary key in the table, and so is "read-only" and cannot be changed in the EditItemTemplate. However, it is required to populate the @ProductID parameter of the SQL UPDATE statement - which means it must be placed in an ASP.NET server control (in this case a Label), and bound to the source rowset using the Bind method. If the Eval method is used here, the control will not be able to populate the @ProductID parameter in the SQL statement.

 

The ProductID is not required in the InsertItemTemplate, because this is an IDENTITY column in the database - and so it will be populated automatically when a new row is added. For this reason, the SQL INSERT statement has no parameter for the ProductID, hence there is no requirement to display the value in a server control within this template, or use the Bind method. The only value that is required is the new product name, and the Bind method used with the TextBox where this is entered will push the new value into the database table.

 

The screenshot below shows the results. This example, bind-method.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.

 

 

When to Use the Bind Method

When you use templates in a GridView, DetailsView or FormView control, you should be aware of a few points:

 

  • The Bind method is responsible for providing the values for the parameters declared in the SQL statements that push changes to the data back into the database. Therefore, all the controls that provide values for the parameters in the SQL statement for the current operation must use the Bind method. In the earlier example, the control for the ProductID in the EditItemTemplate is a Label that doesn’t allow the value to be edited (it is the primary key for the row). However, the value is required to populate the @ProductID parameter in the SQL UPDATE statement, and so the Bind method is used, rather than the Eval method. However, because ProductID is an IDENTITY column within the database, a value isn’t required in the SQL INSERT statement - and a bound control is not required in the InsertItemTemplate section.

 

  • In general, the Bind method should only be used only in an EditItemTemplate and an InsertItemTemplate. It should not be used (or, in fact, required) in an ItemTemplate, AlternatingItemTemplate, or SelectedItemTemplate.

 

  • A list control in which the Bind method is used must be populated by a data source control that is connected to the list control through the DataSourceID property or attribute. It cannot be used for controls that are populated (as in ASP.NET 1.x) by assigning a rowset to their DataSource property.

 

  • Every control that uses the Bind method to populate one or more of its attributes must have a unique user-declared value for its ID property (as shown for the controls in the listing above).

 

  • The Bind method cannot be used in a DataList or a Repeater control, or in any other type of control, and it cannot be used at Page level outside all of the controls. In effect, the only controls to where you can use the Bind method are the GridView, DetailsView and FormView controls.

The New Data Binding Syntax for XML Data

Increasingly, the data you have to work with in your Web applications is presented as XML. It might be static XML documents, or (more likely) XML that has been dynamically generated by another application or a Web Service. ASP.NET 2.0 contains several new data source controls, and three of these are specifically designed to work with XML data:

 

  • The XmlDataSource control is designed to work with hierarchical data presented as XML, in other words data where there can be multiple and irregular nesting of elements.

 

  • The DataSetDataSource control is designed to work with XML that represents a flat table, rather than being hierarchical in nature. In other words, XML data that effectively represents a DataTable within a DataSet.

 

  • The SiteMapDataSource control is a logical extension of the XmlDataSource control, and is specifically designed to expose an XML-formatted map of a Web site or application. It is generally used along with several other new controls in ASP.NET 2.0 that generate menus and other site navigation aids.

 

This article does not explore the new data source controls, but instead focuses on the way that data binding is used to access and present individual items of data that these controls expose.

The XPathBinder Object

The issue at hand is: how do you specify an element or a series of elements when creating output where the data is XML rather than the more usual "rows and columns" format? The existing Eval and Bind methods rely on the column names, and are used when the source data is a rowset - such as that exposed by the SqlDataSource control.

 

The answer is that there is a new binding object in ASP.NET 2.0, called the XPathBinder. This works much like the DataBinder object that is now the default context when data binding to rowset data. The XPathBinder object exposes two methods that can be used to select items from an XML document, the Eval method and the Select method.

 

The Eval method, which has exactly the same syntax as the DataBinder.Eval method, returns the value of a single element or attribute from the current context. The current context is effectively the set of elements exposed by the parent of this element, rather like the set of columns in the current row of a relational data rowset. You can optionally format the returned value using the same approach as described for the DataBinder.Eval method:

 

<%# XPathBinder.Eval(Container.DataItem, "xpath"[, "format"]) %>

 

However, in line with the simplified syntax for rowset data binding, the equivalent has been provided for XML data sources as well. Rather than specifying the XPathBinder.Eval method, you simply use a method of the TemplateControl named XPath:

 

<%# XPath("xpath"[, "format"]) %>

 

The second method of the XPathBinder is the Select method. This method is designed to return a collection of node values, rather than a single value (like the Eval/XPath method does). For this reason, there is no format parameter for the Select method. The full syntax of this method is:

 

<%# XPathBinder.Select(Container.DataItem, "xpath") %>

 

Again, there is a simplified form:

 

<%# XPathSelect("xpath") %>

 

The xpath parameter to the XPath and XPathSelect methods is an XPath expression that identifies the nodes that you want to bind to the controls in your page. XPath expressions are extremely powerful, and can be used to return single nodes (elements or attributes) from anywhere in an XML document, or collections of nodes. For more details of XPath and the techniques for writing XPath expressions, start at the W3C site at http://www.w3.org/TR/xpath.

Using the XPath Method

To demonstrate the XPath method, we need some XML to act as the source data. For simplicity, this example uses a disk file names employees.xml, which looks like this:

 

<?xml version="1.0" ?>

<employee-list>

  <employee id="2456">

    <name>Mike</name>

    <department>Sales</department>

    <phone>3867</phone>

  </employee>

  <employee id="1965">

    <name>Nikita</name>

    <department>Marketing</department>

    <phone>1442</phone>

  </employee>

  ... more employees here ...

</employee-list>

 

To expose this for data binding, we use an XmlDataSource control, specifying the disk file as the XML source data:

 

<asp:XmlDataSource id="ds1" runat="server" DataFile="employees.xml" />

 

Now the data can be bound to any control using the new XML data binding statements. This example uses a FormView control, with the DataSourceID attribute set to the ID of the XmlDataSource control so as to link the two controls together. Then, inside the ItemTemplate section, individual controls that generate the output for the FormView control are declared, just as in the earlier examples that used a SqlDataSource control. This time, however, the XPath data binding method is used, because the items in the source data are XML nodes:

 

<asp:FormView ID="formview1" runat="server" DataSourceID="ds1" AllowPaging="True">

  <ItemTemplate>

    ID:<b>

    <asp:Label ID="lblID" Runat="server"

         Text='<%# XPath("@id") %>' /></b><br />

    Name:<b>

    <asp:Label ID="lblName" Runat="server"

         Text='<%# XPath("name") %>' /></b><br />

    Dept:<b>

    <asp:Label ID="lblDept" Runat="server"

         Text='<%# XPath("department") %>' /></b><br />

    Phone:<b>

    <asp:Label ID="lblPhone" Runat="server"

         Text='<%# XPath("phone") %>' /></b>

  </ItemTemplate>

</asp:FormView>

 

Each Label control in the ItemTemplate of the FormView control is bound to one of the nodes in the source data. The nature of the XML file means that the <employee> element is the one that is repeated within the FormView control (in other words, it is the equivalent of the "rows" in relational data terms). So the Label controls that display the name, department and phone number can be bound directly to the child elements within each <employee> element by using the element name in the XPath method. The ID of each employee is stored in an attribute of that <employee> element, and so in this case the attribute name is used in the XPath method, as XPath("@attribute-name").

 

The screenshot below shows the results. This example, xpath-xmldatasource.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.

 

Using the XPathSelect Method

The XPath method shown in the previous example returns a single value based on the XPath provided as a parameter. The XPathSelect method uses an XPath expression to return a collection of nodes from an XML document. To demonstrate the XPathSelect method, we use a more complex XML file as the data source. You can see that it contains a second level of nested elements in the form of multiple phone numbers for each employee:

 

<?xml version="1.0" ?>

<employee-list>

  <employee id="1437">

    <name>Mike</name>

    <department>Sales</department>

    <phone-list>

      <phone>3867</phone>

      <phone>773-6482</phone>

      <phone>(278) 555-3678</phone>

      <phone>(643) 555-1101</phone>

    </phone-list>

  </employee>

  <employee id="7290">

    <name>Nikita</name>

    <department>Marketing</department>

    <phone-list>

      <phone>1442</phone>

      <phone>(278) 555-8521</phone>

      <phone>(532) 555-4444</phone>

    </phone-list>

  </employee>

  ... more employees here ...

</employee-list>

 

An XmlDataSource control is used to expose this data for data binding, in exactly the same way as the previous example. However, the XPathSelect method can now be used to get a collection of phone numbers for each employee. In the next listing, the first section of the ItemTemplate is the same as in the previous example.

 

<asp:FormView ID="formview1" runat="server" DataSourceID="ds1" AllowPaging="True">

  <ItemTemplate>

    ID:<b>

    <asp:Label ID="lblID" Runat="server"

         Text='<%# XPath("@id") %>' /></b><br />

    Name:<b>

    <asp:Label ID="lblName" Runat="server"

         Text='<%# XPath("name") %>' /></b><br />

    Dept:<b>

    <asp:Label ID="lblDept" Runat="server"

         Text='<%# XPath("department") %>' /></b><br />

 

    Phone Numbers:<br />

    <asp:Repeater DataSource='<%# XPathSelect("phone-list/phone") %>' runat="server">

      <ItemTemplate>

        * <asp:Label ID="lblPhone" runat="server"

               Text='<%# XPath(".") %>' /><br />

      </ItemTemplate>

    </asp:Repeater>   

 

  </ItemTemplate>

</asp:FormView>

 

The difference is in the addition of a Repeater control to display the list of phone numbers for each employee. The XPathSelect method is used to set the DataSource for the Repeater to a collection of the elements containing the phone numbers. The XPath "phone-list/phone" selects all the <phone> elements that are children of the current <phone-list> element (the one within the current <employee> element). Then, inside the Repeater control, the value of each <phone> element is displayed in a Label control. The XPath ".", which used to set the Text attribute of the Label control, simply returns the value of the current element.

 

The screenshot below shows the results. This example, xpathselect-xmldatasource.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.

 

Summary

This article focuses on the new and improved syntax for data binding in ASP.NET 2.0, using the new data source controls and both the new and existing controls for displaying data in "list" or "grid" format. The aim is to explain and demonstrate the uses of the new data binding syntax, rather than how the data source and display controls themselves work. But, as you have seen, the combination of all three technologies - data binding, data source controls and the new list and grid controls - makes it easy to create attractive pages for displaying data with very little effort.

 

In summary, there are three types of data binding statement you can use in ASP.NET 2.0. For rowset data (i.e. data that is in row and column format) you can use the existing v1.x syntax, or the simplified Eval syntax, to bind to a data column. And, as in v1.x, you can also use these statements to bind to the property of another control, or to the results of an expression:

 

<%# Container.DataItem("[column-name|property|field]") %>

<%# DataBinder.Eval("[column-name|property|field]"[, "format"]) %>

<%# Eval("[column-name|property|field]"[, "format"]) %>

 

When using the new GridView, DetailsView or FormView controls, where you implement automatic updates to the data source and use templates to display the data, you must use the new Bind method for any controls containing values that are used as parameters in the SQL INSERT, UPDATE and DELETE statements:

 

<%# Bind("column-name"[, "format"]) %>

 

When the source data is XML, rather than a rowset, you must use the XPath or XPathSelect method in the data binding statements. Both of these methods accept an XPath expression that identifies the node or nodes to select. The XPath method returns a value from a single node (attribute or element), while the XPathSelect method returns a collection (as an ArrayList) of values from multiple matching nodes:

 

<%# XPath("xpath-expression"[, "format"]) %>

<%# XPathSelect("xpath-expression") %>

 

So, with all this choice in data binding capabilities, you'll never again have to write code that iterates through your data to build up an HTML table!

 

©2004 Stonebroom Limited, England. By Alex Homer, alex@stonebroom.com