Using the DataGrid Control in Pocket PC Applications

 

Christian Forsberg
businessanyplace.net

September 2003

Applies to:
   Windows Mobile™ 2003 software for Pocket PCs
   Microsoft® .NET Compact Framework version 1.0
   Microsoft Visual Studio® .NET 2003

Summary: Learn how the DataGrid control can be used to view and update data efficiently in your Pocket PC applications. This article will explain why it is important and show you how it can be done. (6 printed pages)

Download datagrid_control.exe

Contents

Table Data
The DataGrid Control
DataGrid Sample
Code Walkthrough
Conclusion

Table Data

When implementing enterprise Pocket PC applications, there is almost always a need to view data as tables. The most common scenarios are search or selection forms where you enter a number of search criteria and get a search result as a table. A table is a very efficient way to present data, as you make efficient use of the screen space.

The DataGrid Control

The DataGrid control included with the Microsoft® Visual Studio® .NET 2003 is a powerful control that enables you to view table data with a variety of options. The control can be bound to a DataTable, DataView, ArrayList or any other object that support the IListSource or IList interfaces.

Let's see how the DataGrid control can be used in a sample Pocket PC application.

DataGrid Sample

This is a sample application for the Pocket PC created with Visual Studio .NET 2003, C#, and the Microsoft .NET Compact Framework. It shows how to view and update data using the DataGrid control. The application consists of one form:

Figure 1. DataGrid sample

The sample starts by loading the orders table (a subset of the original orders table from the Northwind sample database) into a grid, and then a number of column styles are applied to create a nice look. Each of the columns can be sorted by tapping on the column header, and subsequent taps on the same header toggles the sort order between ascending and descending.

A nice feature is that each cell in the grid is editable. As soon as a cell is tapped and receives the input focus, the value in the cell can be updated (see Figure 1). As soon as another cell is selected, the edited cell is updated and the new cell gets editable. Note also that the Soft Input Panel (SIP) is automatically enabled (shown) as soon as a cell gets the input focus. A possible enhancement to the sample would be to scroll the selected cell into view if covered by the SIP.

Now, let's take a look at what the code looks like.

Code Walkthrough

In the sample code, the DataGrid control is named grdOrders. To load the orders table (saved as an XML file) into the DataGrid control, the only code you need is:

DataSet ds = new DataSet();
ds.ReadXml(@"\Program Files\DGrid\orders.xml");
grdOrders.DataSource = ds.Tables[0];

However, if you only do this you will get a very simple grid and each column header will have the name of the table field. To make the grid look good, use table styles. A table style can contain a number of column styles—one for each column you want to view in the grid. In the sample, the columns included are the order date and the name of the customer receiving the goods. Here's the code to set the style from code:

DataGridTableStyle ts = new DataGridTableStyle();
ts.MappingName = "Order";

// Order date column style
DataGridColumnStyle orderDate = new DataGridTextBoxColumn();
orderDate.MappingName = "OrderDate";
orderDate.HeaderText = "Date";
ts.GridColumnStyles.Add(orderDate);

// Shipping name column style
DataGridColumnStyle shipName = new DataGridTextBoxColumn();
shipName.MappingName = "ShipName";
shipName.HeaderText = "Customer";
shipName.Width = this.Width - orderDate.Width - 37;
ts.GridColumnStyles.Add(shipName);

grdOrders.TableStyles.Add(ts);

Each column style (DataGridColumnStyle) is set up with a field name to map to (MappingName property), header text to show (HeaderText property), and custom column width (Width property). Both column styles are added to the table style and finally the table style is added to the DataGrid control (grdOrders). Here the styles are created with code, but the styles can also be created in the forms designer.

When the grid looks good, there are a number of common features that the grid can support. An example is editing. As there is no native support for editing in the DataGrid control, this needs to be implemented manually. One way to do this is by using a hidden TextBox control that is made visible when a cell is selected and hidden when editing is complete. These are the variables that are needed to do this:

private DataGridCell editCell;
private bool inEditMode = false;
private bool inUpdateMode = false;

We need to track which cell is active for editing (editCell), if the cell is in edit mode (inEditMode), and if we are currently updating a cell (inUpdateMode).

The code to handle the editing looks like this:

private void grdOrders_CurrentCellChanged(object sender,
  System.EventArgs e)
{
  if (!inUpdateMode)
  {
    if (inEditMode && !grdOrders.CurrentCell.Equals(editCell))
    {
      // Update edited cell
      inUpdateMode = true;
      grdOrders.Visible = false;
      DataGridCell currentCell = grdOrders.CurrentCell;
      grdOrders[editCell.RowNumber, editCell.ColumnNumber] =
        txtEdit.Text;
      grdOrders.CurrentCell = currentCell;
      grdOrders.Visible = true;
      inUpdateMode = false;
      txtEdit.Visible = false;
      inEditMode = false;
    }

    // Enter edit mode
    editCell = grdOrders.CurrentCell;
    txtEdit.Text = (string)grdOrders[editCell.RowNumber,
      editCell.ColumnNumber];
    Rectangle cellPos = grdOrders.GetCellBounds(editCell.RowNumber,
      editCell.ColumnNumber);
    txtEdit.Left = cellPos.Left - 1;
    txtEdit.Top = cellPos.Top + grdOrders.Top - 1;
    txtEdit.Width = cellPos.Width + 2;
    txtEdit.Height = cellPos.Height + 2;
    txtEdit.Visible = true;
    inEditMode = true;
  }
}

When a cell is tapped (both inEditMode and inUpdate mode is false), the current cell is saved (editCell). Then, the hidden TextBox (txtEdit) gets the current cell contents, is repositioned to the location of the current cell, and is made visible (over the current cell). When editing is complete and another cell is selected, the event code is disabled (inUpdateMode set to true) and the new cell is saved (currentCell) while the edited cell gets updated from the TextBox control. During the update the grid is not updated (Visible set to false), and when the update is complete the TextBox is hidden again.

Another common grid feature is the ability to sort by tapping on the column headers. The code to do this looks like this:

private void grdOrders_MouseUp(object sender,
  System.Windows.Forms.MouseEventArgs e)
{
  DataGrid.HitTestInfo hitTest = grdOrders.HitTest(e.X, e.Y);
  if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
  {
    // Exit edit mode
    txtEdit.Visible = false;
    inEditMode = false;

    // Sort tapped column
    DataTable dataTable = (DataTable)grdOrders.DataSource;
    DataView dataView = dataTable.DefaultView;
    string columnName = dataTable.Columns[hitTest.Column].ColumnName;
    if (dataView.Sort == columnName)
      dataView.Sort = columnName + " DESC";
    else
      dataView.Sort = columnName;
  }
}

If a header is tapped, the first thing to do is to make sure that any current cell editing is cancelled. Then a DataView is created and sorted by the tapped column. If a column gets tapped a second time the sort order is changed to descending. Subsequent taps will toggle the sort between ascending and descending until another column is tapped.

Conclusion

The DataGrid control is a powerful tool to view (and even edit) data in your Pocket PC applications. The control provides a huge number of features, and this article just covered some of the most interesting: data binding, in-grid editing, and sorting. Your next step is to build further on the sample to explore even more cool tricks that can be achieved with this control.