Browse DevX
Sign up for e-mail newsletters from DevX


A Look Under the Hood of Windows Forms Data Binding : Page 5

In Windows Forms, the data binding machinery is highly sophisticated and designed to meet common needs of former client/server applications, now migrating to the more modern .NET multi-tier design. The binding manager is a logical component that plays a key role as it enables data-bound controls grouped in a container control and bound to the same data source object to detect each other's changes and reflect their own user interface automatically.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Codeless Master/Detail
The code in Listing 1 creates a form with three DataGrid controls each displaying one of three inter-related tables: employees, orders, and order details. When the user selects an employee, the form updates the order and detail view to show all orders processed by the employee, and all the items included in the first order in the view. The user manually selects the item in the first DataGrid and the other two DataGrids update themselves automatically based on the services of the binding manager.

Let's focus on the following excerpt from Listing 1.

EmployeeGrid.DataSource = m_data EmployeeGrid.DataMember = "Emp" OrdersGrid.DataSource = m_data OrdersGrid.DataMember = "Emp.Emp2Ord" DetailsGrid.DataSource = m_data DetailsGrid.DataMember = "Emp.Emp2Ord.Ord2Det"

All three DataGrids are bound to the same data source object—a DataSet object named m_data in the example. The DataMember property of a data-bound control selects a collection of data out of DataSet. In most cases, DataMember points to the name of a child DataTable object. The EmployeeGrid control, for example, displays the contents of the Emp table. A bit more interesting is the expression assigned to the DataMember property of the other two DataGrid controls. The expression is based on a custom syntax—a dot-separated sequence of strings—that data-bound controls can interpret. The value of the DataMember property is known as a navigation path within the data source.

A navigation path resolves to a list or property in the data source. The expression typically includes the table name plus column name or one or more relation names. A relation name is the name of any DataRelation object defined between a pair of DataTables in the DataSet. Let's consider the expression Emp.Emp2Ord, which is the name of a data relation object defined as follows.

Dim col1 As DataColumn Dim col2 As DataColumn col1 = m_data.Tables("Emp").Columns("employeeid") col2 = m_data.Tables("Ord").Columns("employeeid") Dim rel1 As DataRelation rel1 = New DataRelation("Emp2Ord", col1, col2) m_data.Relations.Add(rel1)

The data relation defines a link between the employees and the orders table set on the common employeeid column. When assigned to the DataMember property of a grid, the expression Emp.Emp2Ord indicates that the grid will display all records from the orders table related to the currently selected record on the parent table of the relation—the employees table.

A similar pattern determines the meaning of the expression Emp.Emp2Ord.Ord2Det. In this case, displayed records come from the table with order details and consist of all items in the currently selected order.

When a DataGrid control is bound to a data source, it retrieves the current binding manager for the data source and hooks up the CurrentChanged event. When the current record on the data source changes (no matter which control modified the selection), the DataGrid receives an event. At this point, each DataGrid control by default looks at the navigation path stored in its DataMember property. The first token, if any, is considered as the table name. The next token can either be a column or relation name. If it is a relation name then the grid retrieves all the records in the child table that match the relation. This is accomplished using the GetChildRows method on the DataRow class.

DataRow parentRow = ... ; DataRow[] childRows; childRows = parentRow.GetChildRows(relName);

Figure 2: A master/detail page with three grids.
As you can see, GetChildRows returns an array of DataRow objects. The elements in the array are then used to populate the grid. In this way, each DataGrid with a proper navigation path can automatically refresh its contents whenever a selection changes in the logical tree of data. As a margin note, consider that no DataGrid control you may have in the form is aware of the others. Figure 2 shows the form of Listing 1 in action in a sample application.

Any click on a grid to select a record pushes changes to other grids down the hierarchy. Which grid is the master, and which is the slave. is not written anywhere; or, at least, it is not written clearly or in code. The grid's role is wholly determined by the navigation path assigned to the DataMember property of the control. The data to display is extracted from the same data source object—the DataSet class.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date