The Binding Context
At that point I decided to take the plunge into the intricacies of Windows Forms data binding. The BindingContext
property was the first element I selected for further investigation. The property is common to all Windows Forms controls as it is implemented in the base Control
class. So what's the binding context of a Windows control?
Technically speaking, the binding context is a collection of objects, as the code below demonstrates.
public class BindingContext :
Whenever you set the DataSource
property of a data-bound control (i.e., a ComboBox control), the control retrieves and updates its binding context to reflect the new data source. Each control has its own unique binding context. If no context is explicitly assigned, the control inherits the binding context of the container where the control is hostedtypically the form or a panel control.
|Whenever you set the DataSource property of a ComboBox control, the control retrieves and updates its binding context to reflect the new data source.|
What kinds of objects are stored in the binding context? The binding context contains binding managers
. A binding manager exists for each distinct data source used by data-bound controls in the container. For example, if you a have a DataGrid and a ComboBox control on a form, each bound to a different data source object, the binding context of the form will contain two entriesone for each data source. If two or more controls in the form share the same data source object, a single binding manager will be created in the binding context. The two preceding code snippets differ just on the number of binding managers created in the binding context. The two ComboBoxes work in sync when they share the same data source object and subsequently the same binding manager. They work independently from each other when different data source objects are employed. In both cases, and this is the key point, they use the same binding context collection.
A binding manager is an instance of a class that inherits from BindingManagerBase. Figure 1
provides a graphical representation of binding context and binding managers.
|Figure 1: Each data-bound control in the form references a binding context collection. The collection, in turn, contains references to binding managers.|
Two classes in the .NET Framework inherit from BindingManagerBase: CurrencyManager
and PropertyManager. To understand their roles and differences, let's first tackle the behavior of a binding manager. You get a reference to a binding manager through the following code:
bmb = Form1.BindingContext[m_dataSet, "Orders"];
The binding manager in the code snippet manages all controls bound to the Orders table of the specified DataSet. These controls share the information stuffed into the internal members of the specific binding manager type. What this information is, and refers to, depends on the binding manager type.
Binding Context Can Be Control-Specific
Although most controls rely on the inner container's binding context (e.g., the parent form), each control can have its own private binding context. You assign a control a new context by setting the BindingContext
property to a new instance of the BindingContext class. This fact has an important down sidethe control is detached from the form's context and doesn't receive data binding events caused by other controls bound to the same data source. As a result, the control with a new, fresh binding context is no longer synchronized with others.
Binding managers provide a central repository of information for data-bound controls on a Windows Form that are bound to the same data source. In doing so, binding managers enable the synchronization of related controls.
|You can handle events (Format and Parse) to control how the data is marshaled back and forth between the user interface and the back end memory.|
Clients of distributed applications (in most cases, just evolutions of former client/server applications) need to populate rich and sophisticated user interfaces. Typically, they require a lot of work to refresh controls when the selection changes or when a user chooses a different view of data.
Binding managers form the infrastructure of an innovative architecture based on auto-update controls that work in sync and detect changes on the memory objects they're bound to.
For example, suppose you have two DataGrids that form a master/detail view. In a non-Windows Forms scenario, you have to assign each grid an explicit rolebe it master or detail. On the master grid you hook up the SelectionChanged
event and invoke a method on the child grid passing some information like the ID of the selected record. In turn, the child grid uses that information to refresh its view and stay in sync with the master grid.
There's coupling between the two grids; but, more important than that, you have to set any required logical relationship in code.
What if you have several relationships to manage and a cascade of nested tables and views? In this case, the quantity of synchronization and glue code grows easily beyond the reasonable threshold of manageability. Testing and maintaining this kind of code is extremely difficult.
Binding managers, instead, provide a common interface to data-bound controls and enable them to implicitly handle events and query for required data. Data-bound controls are therefore smarter and require much less code to set up even sophisticated clients. In simple cases you can even set up two or more levels of details view in a declarative manner.
Central to the design of the Windows Forms data binding mechanism is the ADO.NET DataSet object. You bind all controls to the same object referencethe DataSetand give each control a different navigation path to make it handle a different subset of data. The DataSet is a collection of tables and relations; the navigation path uses both table and relation names to express, in a custom syntax, the subset of rows the control will display.