DataGrid with a custom header and selection.

One of the questions that has recently come up on the .Net CF MSDN forums was on how to create a custom (owner drawn) header in the DataGrid. This person wanted to implement the look similar to the grid that is used in the Mobile CRM application that has a non standard header and row selection.

crm_mobile

Both are using a gradient filled colors. So I decided to take this up for a challenge to create a similar look by using the standard DataGrid control that comes with .NET CF v2 SP2. Ilya Tumanov from the .NET CF team had create a great sample that shows how to create a custom column types and to override the Paint event in the DataGridTextBoxColumn. In my sample I've reused some code from his sample.

As a first step I have created the CustomSelectionColumn class that inherits from the DataGridTextBoxColumn. Here's how the Paint method looks:

  protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, 
                    int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
 {
     RectangleF textBounds;      // Bounds of text 
     object cellData;     // Object to show in the cell 

     // Check if the row is selected
     if (gridControl.IsSelected(rowNum))
     {               
         DrawBackground(g, bounds, rowNum, backBrush, true); 
     }
     else
     {
         DrawBackground(g, bounds, rowNum, backBrush, false);
     }
            
      // Draw cell background
      bounds.Inflate(-2, -2);    // Shrink cell by couple pixels for text.

      textBounds = new RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height);
      // Set text bounds.
      cellData = this.PropertyDescriptor.GetValue(source.List[rowNum]); // Get data for this cell from data source.

      g.DrawString(FormatText(cellData), this.gridControl.Font, foreBrush, textBounds, this.StringFormat);                       
  }

In order to draw a gradient filled selector in the grid, I went to the MSDN library samples for .NET CF and copied the code from the How to: Display a Gradient Fill article into my project. So the DrawBackround method utilizes the code from this article:

 

 protected virtual void DrawBackground(Graphics g, Rectangle bounds, int rowNum, Brush backBrush, bool selected)
{
    // Create rectangle for drawing       
    Rectangle rc = new Rectangle(bounds.Left - 2, bounds.Top, bounds.Width + 4, bounds.Height);
    // Check if the row is selected
    if (selected)
    {
        // Draw gradient cell selection
        GradientFill.Fill(g, rc, Color.LightBlue, Color.RoyalBlue, GradientFill.FillDirection.TopToBottom);
    }
    else
    {
        g.FillRectangle(backBrush, rc);
    }            
}

 

So this should take care of a custom row selection. Now up to the custom header. A few years ago I had created an owner-drawn header control for a ListView. I have modified the CustomHeader control to use with the DataGrid and added the gradient drawing code to it. Here is the how the result looks:

custom_grid

You can download the full demo code from here.