DekGenius.com
[ Team LiB ] Previous Section Next Section

10.4 The DataGrid Control

So far, we have only looked at complex binding to the ListBox control. However, both this control and its close relative the ComboBox can only show a single property for each item they display. This can be somewhat limiting—in the previous example, it would have been useful to be able to display more information about the orders. (The Northwind database contains information about the due date, the actual fulfillment date, the date on which the order was placed, and the current status of the order, to name a few properties.) Fortunately, Windows Forms supplies a control that supports complex binding and that does not suffer from these limitations: the DataGrid control.

Like the ListBox and ComboBox controls, the DataGrid control supports complex binding. But unlike those controls, it is able to display all the properties of each list item instead of a single property. Example 10-34 shows the C# code used to bind a DataGrid control to the Orders table via the relation with the Customers table.

Example 10-34. DataGrid binding
dataGridOrders.DataSource = ds;
dataGridOrders.DataMember = "Customers.CustomerOrdersRelation";

This is very similar to Example 10-31. The main difference is that where the ListBox control's DisplayMember property was set to a string that specified both the table to be bound to and the property to be displayed, the DataGrid control's DataMember property just describes which table to use—the control will display all the properties. (Remember that if you set the ListBox control's DisplayMember to be the name of the table, it simply calls the data source's ToString method, which is not normally useful.) The DataGrid control is shown in Figure 10-6.

Figure 10-6. The DataGrid control in action
figs/winf_1006.gif

We now have considerably more information than we really wanted. By default, the DataGrid will display every available property. In this case, that includes the CustomerID property, which is extraneous because it will always be the ID of whichever customer is currently selected. We will see how to filter the columns shortly.

Another interesting feature of the DataGrid in Figure 10-6 is that each entry has a + symbol by it. The DataGrid adds this whenever it displays a table that is related to another table. In this case, it has detected the relation that we set up between the Orders table and the Order Details table in Example 10-30. Clicking on the plus symbol expands the row to show all related tables, as shown on the second row. We have only added one related table to the DataSet here, so the grid just shows Order Details. It is drawn to look like a hyperlink because clicking on it drills down into the table, as shown in Figure 10-7.

Figure 10-7. DataGrid showing a related table
figs/winf_1007.gif

The DataGrid is now showing us all rows from the Order Details table that have the same OrderID as the row we selected from the Orders table. Notice that this original row from the Orders table is still visible at the top of the control.

The DataGrid allows relations to be explored to any depth. We no longer strictly need the ListBox control showing the customer—we could just bind the DataGrid to the Customers table, and it would then allow each customer's orders to be explored in the grid. In this example, our DataSet does not have any tables related to the Order Details table, so the rows do not have a + symbol, but if we had included further related tables from the database (such as the Products table), we would be able to drill down further.

So the DataGrid provides a very easy way of allowing users to browse through all the data in a DataSet. The one problem, as has already been observed, is that it sometimes shows too much, so we will now see how to filter what it shows.

10.4.1 Filtering the DataGrid Display

By default, the DataGrid control will display every available property from the data source. Because this is not always appropriate, it also provides a mechanism for controlling which columns are shown and how they are presented.

The DataGrid control has a property called TableStyles. This is a collection of DataGridTableStyle objects that control how the grid will display a particular table. We can add an entry for each table we plan to display to override the grid's default behavior of showing everything

The DataGridTableStyle object itself has a GridColumnStyles property, which is a collection of DataGridColumnStyle objects. The DataGrid will display one column for each DataGridColumnStyle object. So to control which columns appear, we must simply build a DataGridTableStyle object whose GridColumnStyles property only contains DataGridColumnStyle objects for the columns we wish to display.

Building all these objects from scratch is hard work. If all you want to do is prevent certain columns from appearing, it is much easier to let the framework build a complete DataGridTableStyle object for you, and then remove the columns you don't want, as shown in Examples Example 10-35 and Example 10-36.

Example 10-35. Removing unwanted columns from a DataGrid using C#
CurrencyManager cm = BindingContext[ds, "Orders"] as CurrencyManager;
DataGridTableStyle ordersStyle = new DataGridTableStyle(cm);

ordersStyle.GridColumnStyles.Remove(
    ordersStyle.GridColumnStyles["CustomerID"]);
ordersStyle.GridColumnStyles.Remove(
    ordersStyle.GridColumnStyles["OrderID"]);
ordersStyle.GridColumnStyles.Remove(
    ordersStyle.GridColumnStyles["EmployeeID"]);

dataGridOrders.TableStyles.Add(ordersStyle);


cm = BindingContext[ds, "Order Details"] as CurrencyManager;
DataGridTableStyle detailsStyle = new DataGridTableStyle(cm);

detailsStyle.GridColumnStyles.Remove(
    detailsStyle.GridColumnStyles["OrderID"]);

dataGridOrders.TableStyles.Add(detailsStyle);
Example 10-36. Removing unwanted columns from a DataGrid using VB
Dim cm As CurrencyManager = DirectCast(BindingContext(ds, "Orders"), _
                  CurrencyManager)
Dim ordersStyle As New DataGridTableStyle(cm)

ordersStyle.GridColumnStyles.Remove( _
    ordersStyle.GridColumnStyles("CustomerID")) 
ordersStyle.GridColumnStyles.Remove( _
    ordersStyle.GridColumnStyles("OrderID")) 
ordersStyle.GridColumnStyles.Remove( _
    ordersStyle.GridColumnStyles("EmployeeID")) 

dataGridOrders.TableStyles.Add(ordersStyle) 


cm = DirectCast(BindingContext(ds, "Order Details"), _
      CurrencyManager)
Dim detailsStyle As New DataGridTableStyle(cm) 

detailsStyle.GridColumnStyles.Remove( _
    detailsStyle.GridColumnStyles("OrderID")) 

dataGridOrders.TableStyles.Add(detailsStyle)

The easiest way to get the framework to create a fully populated DataGridTableStyle object is to pass the CurrencyManager for the table in question as a constructor parameter. We then remove the columns we don't wish to see. (In this case, we are removing all the key columns because they don't contain information that is meaningful to the end user.) We then add the object to the DataGrid control's TableStyles property, so that the DataGrid knows which columns to display when showing the Orders table. Because the DataGrid is able to follow relations, it can also show the Order Details table, so we repeat the process for that table, removing the OrderID column. The result is shown in Figure 10-8.

In general, it is more efficient to filter out unwanted columns at the SQL level—if you do not need data, you should not ask the database to send it to you because you will be wasting time, CPU cycles, and network bandwidth. However, in this particular example, we do not have this luxury. We need the ID columns because we are using them to enable the relational master/details view, so filtering in the DataGrid is still the correct technique.


Figure 10-8. A DataGrid with filtered columns
figs/winf_1008.gif

The DataGrid control's table and column style support is not limited to filtering columns. It can also be used to control certain aspects of the way in which data is displayed. For example, the DataGridColumnStyle class has a Width property allowing the column width to be changed, and its HeaderText property allows different text to be shown in the column header. See the reference section for further details.

    [ Team LiB ] Previous Section Next Section