Composing a Data-driven Windows Form
Let's proceed step by step with the creation of a data-driven Windows Forms application. The idea is to build a form-based application that displays and edits data from multiple tables in the same database-guess what-the Northwind database. Figure 1
shows the final application.
|Figure 1: The final destination of the code in this article.|
The form counts a few data-bound controls plus a handful of data connector controls. You typically start by adding the BindingNavigator control to let users navigate through the records of a bound data source. The BindingNavigator control has a VCR-like user interface. It simply selects a particular record in the data source and makes it available through a general-purpose programming interface. The BindingNavigator's user interface makes me recall the command bar of Microsoft Access.
In Windows Forms 2.0, most controls don't bind directly to a collection object; rather they use an intermediate objectthe binding sourcewhich in turn is bound to a classic enumerable data source object. The BindingNavigator control is no exception.
A binding source component is primarily designed to simplify binding between controls on a form and bound data. It also provides a number of additional services such as currency management and change notification. As mentioned, a binding source component adds a layer of indirection between user interface elements and back-end data, as illustrated in Figure 2.
|Figure 2: Binding source components sit in between the user interface and data source.|
You attach the binding source component to a physical data source and then bind the controls on the form to the binding source. From now on, any data-related interaction with the data source is accomplished through the binding source. Typical operations include navigation, retrieval, sorting, filtering, and update.
A binding source component in .NET Framework 2.0 is an instance of a class that extends the BindingSource class. Note that although the terminology is relatively new and specific to .NET Framework 2.0, the core concepts behind a binding source component should be nothing new to expert .NET Windows developers. You may have heard in past years of something called currency managers and binding context?
Well, the binding source component is simply a UI-less component purposely created to let developers manage binding objects from within Visual Studio 2005 and mostly in a declarative manner.
The BindingSource Class
The BindingSource class wraps a data source and exposes it through its own object model. Table 1 lists the main properties of the BindingSource base class.
Table 1: The programming interface of the BindingSource class.
||Indicates whether items in the underlying data source can be edited.
||Indicates whether the new items can be added to the underlying data source.
||Indicates whether items can be removed from the underlying data source.
||Gets the number of items in the underlying data source.
||Gets a reference to the associated currency manager.
||Gets the current item in the underlying data source.
||Indicates a specific list in the data source.
||Indicates the data source that the connector binds to.
||The expression used to filter the data source.
||Indicates whether the underlying data source is read-only.
||Indicates whether the items in the underlying data source are sorted.
||Retrieves the data source item at the specified index.
||Gets the list that the connector is bound to.
||Indicates the index of the current item in the underlying data source.
||Indicates the column names used for sorting, and the sort order.
||Indicates the direction the items in the data source are sorted.
||Gets the PropertyDescriptor object that is being used for sorting the data source.
||Indicates whether the data source supports multi-column sorting.
||Indicates whether the data source supports change notification.
||Indicates whether the data source supports filtering.
||Indicates whether the data source supports searching.
||Indicates whether the data source supports sorting.
It is essential to note that a BindingSource object is designed to manage both simple and complex data binding scenarios, meaning that it incorporates functionality from both CurrencyManager and PropertyManager in the .NET Framework 1.x. In light of this, note that what in Table 1 is referred to as the underlying data source is often a collection (e.g., a typed dataset) but can also be an individual object (for example, a stand-alone DataRow).
As you can see from the properties in Table 1, the binding source component features a Position member that indicates the index of the currently selected data item. The BindingSource class doesn't provide any user interface, so the "selection" here is purely logical. It is up to bound controls to transform the logical selection into something visible and meaningful to users. The Current property is a shortcut to retrieve the data item found at the currently selected position. The BindingSource class also exposes methods to move the selection backward and forward, to jump to a particular position, and an event to signal that the currently selected element has changed.
To bring up these functionalities and make them quickly and easily emerge to the user interface level, you can use the BindingNavigator control and associate it with a binding source. Each time a user clicks on the VCR-like buttons in Figure 1, the Position and Current properties on the binding source are updated and the CurrentChanged event fires. As in Windows Forms 1.x data binding, controls listening to these events receive notification and can properly update their own user interface. This mechanism makes possible the trick of automatic selection change and view synchronization between otherwise unknown and totally unrelated data grids. Let's proceed with the definition of a data source in Visual Studio 2005.