Monday, September 19, 2011

Windows Forms Data Binding - Data Consumers and Binding Controls

Data Consumers
A data consumer is an object or component that uses the data exposed by a data provider with the intent to display or modify that data. In Windows Forms, a data consumer is typically a data-bound control. Simple data-bound controls include, but are not limited to, TextBox, Label, CheckBox, and RadioButton controls. These controls can display only one data value provided by a data source. On the other hand, the DataGrid, ListBox, and ComboBox controls can display a list of values. These controls are therefore referred to as complex data-bound controls.

Binding and BindingContext
Windows Forms controls support either simple binding or complex binding. Controls that support simple binding include the TextBox control. A TextBox control can support only one data value at a time. The following example shows how to bind a TextBox control with the FirstName column of a Customers DataTable object:

        TextBox nameTextBox = new TextBox();
        DataSet dataSet = CreateMyDataSet();   
        nameTextBox.DataBindings.Add("Text", dataSet, "Customers.FirstName");
Every Windows Form control has a DataBindings property, which is an instance of ControlBindingsCollection. The ControlBindingsCollection class represents a collection of Binding objects that bind the properties of controls to data source members. Whenever the data source member changes, the control’s property is automatically updated to reflect the change,and vice-versa. Different properties of the same control can be bound to different data sources.

Every container control on a form, including the form itself, contains at least one BindingContext object. Actually, all controls derived from System.Windows.Forms.Control have the BindingContext property, but only container controls really make use of it. Noncontainer controls simply return the BindingContext object of their immediate container. A BindingContext object 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 object enables retrieval of any particular data source. Specifically, a BindingContext object manages a collection of BindingManagerBase objects. BindingManagerBase is an abstract class thatenables synchronization of data-bound controls that are bound to the same data source. A BindingContext object can be visualized as follows (The dashed lines represent the BindingContext object):Form


In the previous figures, the BindingContext object basically 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 object 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 object:

BindingManagerBase customers = this.BindingContext(DataSet"Customers");
Here is the syntax for creating a new BindingContext object:

groupBox1.BindingContext = new BindingContext();
groupBox2.BindingContext = new BindingContext();

In the previous example, two BindingContext objects are created and are assigned to two GroupBox controls. This allows the contained controls in both GroupBox controls to be bound to the same data source, but using two different binding managers.

Any data source that is bound to a Windows Forms control is associated with a CurrencyManager object. Actually, the true name for CurrencyManager should be “concurrency manager” or “current manager.” During the days of ActiveX Data Objects (ADO), the data source object itself kept track of the current record. The problem with this approach was that multiple data consumers could not reuse the same data source object concurrently in an efficient manner. For example, if there were two Grid controls on a form
that used ADO to display their data, and if both Grid controls used the current record for highlighting purposes, there would have been no way for each Grid control to highlight a different item at the same time. With .NET, the current record is no longer maintained in the data source object itself, which makes the data source object truly disconnected from the actual data store. The current record is maintained by a CurrencyManager object. A CurrencyManager object has a one-to-one relationship with a data source.
A CurrencyManager object 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 object per data source per BindingContext object.) The following diagram shows the relationship between a Form control, a Panel control,CurrencyManager objects, and data sources:

In the previous diagram, the Form control contains the automatically created
BindingContext object, which contains two CurrencyManager objects, one managing an array and the other managing a collection. The Panel control contains a newly created BindingContext object (remember that only the Form control’s BindingContext object is created by default), which also contains two CurrencyManager objects, one managing the same collection that is bound to the Form control and the other managing a DataTable object. Under normal circumstances, only one CurrencyManager object 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 previous diagram, a particular control has three properties that are participating in data binding, as you can note from the three Binding objects. These bindings are stored in the control’s ControlBindings property, which is an instance of ControlBindingsCollection.

Remember, the
ControlBindingsCollection class is a collection of Binding objects, and a Binding object 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 object ensures that the properties that are associated with the same data source are synchronized

The PropertyManager class is used to identify and maintain the current property of an object. PropertyManager is derived from BindingManagerBase, but oddly, most of all of the base properties and methods are overridden to do nothing. For example, setting the Position property of the class has no effect. Also, the AddNew and RemoveAt methods throw an exception of type NotSupportedException. Your guess is as good as mine as to why this class was derived from BindingManagerBase. As of this writing, the PropertyManager class is only used by the PropertyGrid control. The PropertyGrid control uses the current property to raise events, display property descriptions, and invoke the appropriate editors.
The following code shows how to return a PropertyManager object from a BindingContext object:

            Customer singleCustomer = new Customer();
            PropertyManager pm = this.BindingContext(singleCustomer);

Next: Simple Binding Example

No comments :

Post a Comment