Windows Forms Data Binding

One of the most powerful aspects of .NET and Windows Forms is data binding. Historically, data binding was used to bind views to data stored in databases. Some database management systems, such as Microsoft Access, have provided GUI APIs to help developers quickly bind to data.

 

This sample is taken from Chapter 6: "Windows Forms Data Binding" of the Blue Vision Title "Developing .NET Custom Controls and Designers using C#"


Binding and BindingContext

.NET Controls either support simple binding or complex binding. Controls that support simple binding include the text box. A text box can only support one data value at a time. The following example shows how to bind a text box control with a name field of a Customers DataTable:

TextBox nameTextBox = new TextBox();

DataSet dataSet = CreateMyDataSet();

nameTextBox.DataBindings.Add("Text", dataSet, "Customers.FirstName");

Binding

Every Windows Form control has a DataBindings property, which is an instance of ControlBindingsCollection. The ControlBindingsCollection is a collection of Binding objects, which bind the property of a control to a data source member. Whenever the data source member changes, the controls property is automatically updated to reflect the change, and vice versa.

Different properties of the same control may also be bound to different data sources.

BindingContext

Every container control on a Windows Form, including a form itself, contains at least one BindingContext. Actually, all controls derived from System.Windows.Forms.Control have the BindingContext property, but only container controls really make use of it. Non-container controls will simply return the BindingContext of their immediate container. A BindingContext is just an object that provides binding support to multiple data sources. Since more than one data source can be viewed on a form, the BindingContext enables retrieval of any particular data source. Specifically, a BindingContext manages a collection of BindingManagerBase objects. BindingManagerBase is an abstract class that enables synchronization of data-bound controls that are bound to the same data source. A BindingContext can be visualized as follows (The dashed lines represent the BindingContext):

In the pictures above, the BindingContext simply says, "I will manage and  keep track of all controls and their associated data sources and data-bound members. If the current record in the one of the managed data sources changes, I will refresh all controls that I track with the new values."

By default, only one BindingContext is created for a Form, regardless of the number of controls contained on the form.

Here is the syntax for retrieving a data source from the BindingContext:

BindingManagerBasecustomers = this.BindingContext [dataSet, "Customers"];

Here is the syntax for creating a new BindingContext.

groupBox1.BindingContext = new BindingContext();

groupBox2.BindingContext = new BindingContext();

In the snippet above, two BindingContext objects are created and are assigned to two group box controls. This allows the contained controls in both group boxes to be bound to the same data source, but using two different binding managers.

The two classes derived from BindingManagerBase are described next.

CurrencyManager

Any data source that is bound to a .NET Windows Forms control will be associated with a CurrencyManager. Actually, the true name for CurrencyManager should be "concurrency manager" or "current manager." During the days of ADO, the collection itself kept track of the current record. The problem with this approach was that multiple consumers could not reuse the same collection concurrently in an efficient manner. For example, if there were two grid controls on a dialog that used ADO to display their data, and if both grids used the current record for highlighting purposes, there would be no way for each grid to highlight a different item at the same time. With .NET, the current record is not maintained in the data source itself, which makes the data source truly disconnected. The current record is, instead, maintained by the CurrencyManager. A CurrencyManager has a one-to-one relationship with a data source.

A CurrencyManager is automatically created when a Binding object is created, if it is the first time that the data source has been bound. ( Remember that there is only one CurrencyManager per data source per BindingContext.)

The following diagram shows the relationship between a Form, Panel, CurrencyManager objects , and data sources:

In the diagram above, the Form contains the automatically created BindingContext, which contains two CurrencyManager objects, one managing an array, and the other managing a collection. The Panel contains a newly created BindingContext (remember that only the Form's BindingContext is created by default), which also contains two CurrencyManager objects, one managing the same collection that is bound to  the Form, and the other managing a DataTable. Normally, only one CurrencyManager would be created for the Collection; but since there are two BindingContext objects, each must contain its own collection of CurrencyManager objects.

The following diagram shows control binding in action:

In the diagram above, a particular control has three properties that are participating in data binding, as we can note from the three Binding objects. These bindings are stored in the controls ControlBindings property, which is an instance of ControlBindingsCollection. The ControlBindingsCollection class is a collection of Binding objects. A Binding associates the property of a control with a data source member. Whenever the data source member value changes, the control's property is updated, and vice-versa. Two of the bindings are associated with the same data source, while the third one is associated with a different data source. The CurrencyManager ensures that the properties that are associated with the same data source are synchronized.

Comments

Be the first to write a comment

You must me logged in to write a comment.