ata binding is an indispensable feature of ASP.NET that links a user interface element with the underlying data store. ASP.NET 1.1 restricted this data binding to one direction only?from the business object to the web form; but ASP.NET 2.0 introduces support for binding data in both directions. This more flexible approach reduces code, simplifies data binding logic, and simplifies maintenance.
This article explores two-way data binding and illustrates how you can use the feature. The sample application that accompanies the article walks you through the process for implementing two-way data binding in ASP.NET.
What is Data Binding?
The term “data binding” refers to the act of associating a control to an underlying data source in such a way that changes to the data source initiate similar changes in the data contained in the control. Note that controls are bound to an “intermediate data source” and not the “original data source;” in other words the data controls are not bound to data over an active connection, but to an in-memory representation of data.
Understanding Two-Way Data Binding
One familiar example of two-way data binding is the DataSet/DataAdapter combination. You can update the data in the DataSet, and then update the underlying data source using the DataAdapter, or, if changes occur to the underlying data, you can refresh the DataSet using the Fill() method.
With ASP.NET 2.0’s bi-directional data binding, you can eliminate the code required to update a data store by binding the data controls in your presentation layer to the data sources. Because the binding is bi-directional, when users modify the data in the controls the underlying data sources update when users post the web form back to the server.
Typically, you’ve had to use code similar to the following to manage displayed data binding:
//Populate the data controls from a business object txtCode.Text = emp.Code; txtName.Text = emp.Name; //Populate a business object from the data controls emp.Code = txtCode.Text; emp.Name = txtName.Text;
|
If that looks familiar, I’m sure you’re aware of what happens when you have many controls that you need to bind to data?the code volume increases dramatically.
Here’s the simpler approach in ASP.NET 2.0. To enable two-way binding you use the Bind() method as in the following example:
<%# Bind("FieldName") %>
Note that you embed data binding expressions in ASP.NET within special <%# and %> tags. You can use the related Eval() method for one-way read-only data binding, but you must use Bind() for two-way data binding where you might need to update data.
Unfortunately, not all ASP.NET controls support two-way data binding. To work around that, the downloadable sample application that accompanies this article shows you how to implement a two way data binding framework that you can use to bind data to any ASP.NET control.
Sample Two-Way Data Binding Application
To test the framework, you need to build an application that uses it. As a simple example, suppose you have an Employee entity, represented by an EmployeeDO class. This class contains three private fields and corresponding exposed public properties. It implements the IBusinessEntity interface and extends the Component class. IBusinessEntity is a base interface that all entities in this application extend, but this sample application deals exclusively with the Employee entity.
Here’s the code for the IBusinessEntity interface:
public interface IBusinessEntity { Object Code { get; set; } }
The IBusinessEntity interface exposes one property called Code, which functions as a unique ID. Using the IBusinessEntity interface as the base interface or contract for all entities ensures that you can reuse the data binding framework code with any business object. Here’s the code for the EmployeeDO class:
public class EmployeeDO : Component, IBusinessEntity { private object code; private string empName; private string empAddress; public Object Code { get {return code; } set {code = value; } } public String EmpName { get {return empName; } set {empName = value; } } public String EmpAddress { get {return empAddress; } set {empAddress = value; } } }
Create a Container
Next, you need a container in which to store the data binding information. You’ll use this information to bind the controls to the appropriate property of the business object at runtime. This DataBindingRegister class serves that purpose. It holds the data binding information for each control along with the corresponding property of the business object to which the control will be bound.
Here’s the source code for the DataBindingRegister class:
public class DataBindingRegister { #region Fields protected string businessObj; protected string objPropertyName; protected Control ctrlObj; protected string ctrlPropertyName; #endregion #region Properties public string BusinessObject { get { return businessObj; } set { businessObj = value; } } public string BusinessObjectPropertyName { get { return objPropertyName; } set { objPropertyName = value; } }To use the data binding framework you create an array of DataBindingRegister instances and populate them with the necessary data binding information when the web form loads.
public Control ControlObject { get { return ctrlObj; } set { ctrlObj = value; } } public string ControlObjectPropertyName { get { return ctrlPropertyName; } set { ctrlPropertyName = value; } } #endregion }
Build the UI
Finally, you need to build the user interface, which contains a Label that displays the employee’s code, two TextBoxes that display the employee’s name and address respectively, and a Button control.
The following code snippet shows the controls used in the .aspx file for the sample application:
Using the Data Binding Framework
To use this data binding framework you create an array of DataBindingRegister instances and populate them with the necessary data binding information in the Page_Load event of the web form. This array is then added to an instance of the DataBindingRegisterCollection class that holds a collection of DataBindingRegister instances:
void Page_Load(object sender, EventArgs e) { DataBindingRegister [] dataBindingRegister = new DataBindingRegister[2]; // You would normally store the following binding information // in an XML file dataBindingRegister[0] = new DataBindingRegister(); dataBindingRegister[0].ControlObject = this.txtEmpName; dataBindingRegister[0].ControlObjectPropertyName = "Text"; dataBindingRegister[0].BusinessObject= "employee"; dataBindingRegister[0].BusinessObjectPropertyName = "EmpName"; dataBindingRegister[1] = new DataBindingRegister(); dataBindingRegister[1].ControlObject = this.txtEmpAddress; dataBindingRegister[1].ControlObjectPropertyName = "Text"; dataBindingRegister[1].BusinessObject = "employee"; dataBindingRegister[1].BusinessObjectPropertyName = "EmpAddress"; //Now, add the data binding information to the // Data Binding Collection Register this.bindingManager.DataBindings.Add(dataBindingRegister); if (!IsPostBack) { employeeDO = ReadData(); this.bindingManager.BusinessEntity = employeeDO; this.bindingManager.Direction = BindingDirection.FromUIToBusinessObject; this.bindingManager.Bind(this); } }
After storing the data binding information you can bind data from the controls in the user’s interface to the corresponding properties of the business object and vice-versa using the BindingManager.Bind() method. This method accepts an instance of the Page class as a parameter, iterates through the collection of databound control instances and then binds or un-binds data?depending on the binding direction set earlier using the BindingDirection enumeration. The Bind() method returns an IBusinessEntity instance.
IBusinessEntity IBindingManager.Bind(Page form) { foreach (DataBindingRegister dbR in this.dataBindingCollection) { Control control = dbR.ControlObject; if (control.ID != null) { if (this.Direction == BindingDirection.FromUIToBusinessObject) { control.DataBind(); } else if (bindingDirection == BindingDirection.FromBusinessObjectToUI) { PropertyInfo propertyInfo = control.GetType(). GetProperty(dbR.ControlObjectPropertyName, BINDING_FLAGS); object obj = propertyInfo.GetValue(control, null); propertyInfo = this.BusinessEntity.GetType(). GetProperty(dbR.BusinessObjectPropertyName, BINDING_FLAGS); propertyInfo.SetValue( this.BusinessEntity, obj, null); } } } return this.BusinessEntity; }
![]() |
? |
Figure 1. Sample Application: Here’s the sample application showing the two-way databound controls. |
The preceding example calls the Bind() method twice: once in the Page_Load event and once in the Button_Click event. The BindingDirection enum will hold one of two values: either FromBusinessObjectToUI or FromUIToBusinessObject.
That completes the application. Upon execution, it displays the default data bound to the controls in the Page_Load event (see Figure 1). And if you enter new values in the text boxes and then click on the Button control, the form displays the name and address entered in the text boxes after a postback. In both cases, the data binding takes place using the Bind() method, which executes once in each direction.
Data binding in ASP.NET 1.x was unidirectional, i.e., the control could in no way update the underlying data source to which it was bound. While ASP.NET 2.0 introduced two-way data binding, not all the ASP.NET controls supported i; you need to write custom data binding logic such as that discussed in this article to make two-way data binding available for all the controls.