The DataGrid control relies on the data binding architecture we have outlined in the previous section. At the same time, there are some specifics worth a more detailed explanation.
We will start from types of data sources the DataGrid control can be bound to. The most popular types are of course DataTable and DataSet, which are followed by DataView. However, DataGrid is not limited to ADO .NET types and is also capable of handling single-dimension arrays as well as various kinds of lists implementing either the IList or the IListSource interface.
As you have probably noted, all these data sources share a common feature – they all can be uniformly treated as lists having a known number of items. This determines the type of binding manager the DataGrid control uses: it is the CurrencyManager class. In most cases, a single CurrencyManager instance is enough, but when a DataGrid is bound to a DataSet having multiple tables with relations established between them, multiple CurrencyManagers can be created to serve each related table. We will hereafter use the word “list” to define a sequence of items managed by a single CurrencyManager instance.
The DataGrid control exposes two properties related to its data source. The DataSource property gets or sets a data source object the DataGrid instance is bound to. As the DataGrid control is limited with working with a single list at a time, the DataSource property is complemented with the DataMember property to specify a particular list within the DataSource to work with.
The DataMember property contents may vary depending on the nature of the data source and has a generic name “navigation path”. Valid examples of navigation paths are the name of a table in a data set or the name of a relation between master and detail tables in the same data set.
When being bound to a data source, the DataGrid control first creates a CurrencyManager instance for the list specified with the DataMember property value. We will call this instance a primary CurrencyManager instance. Other instances of the CurrencyManager class can be created on demand when, for example, the user navigates a relationship between the parent and the child table within a bound DataSet.
This leads us to the following line of code that returns a CurrencyManager instance a DataGrid instance currently cooperates with:
CurrencyManager cm = this.BindingContext[ theGrid.DataSource, theGrid.DataMember];
You might be concerned at this point about the reason why one should ever bother with CurrencyManagers, and I promise you will see how important their role is.
Data Grid Navigation Mechanics
The DataGrid control maintains a notion of a current row. This row is visually marked with a little black triangle displayed in the corresponding row header. The notion of a current row is used for data editing purposes and for navigating between parent and child tables. DataGrid does not, however, track the current row by itself, relying on its CurrencyManager(s) instead as shown on Figure 2.
You have control over the DataGrid’s current row through the CurrentRowIndex property. This property enables you to retrieve and update current row index corresponding to the primary CurrencyManager’s position. In other words, this property reflects the position within the parent list, and a relation is navigated, the value of this property doesn’t change.
Note though that there is no property to control the position for any of the auxiliary CurrencyManagers. This limitation, however, is no more an obstacle for us, as we already know how to access the CurrencyManager instance for the current list displayed in the DataGrid.