Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Use an Event to Set the Row/Cell BackColor in a Custom DataGridView

3.83/5 (5 votes)
19 Sep 2008CPOL3 min read 1   1.8K  
Introduces an event method to set the row/cell BackColor in a custom DataGridView.

CustomDataGridView

Figure 1: BackColor of Cell[1,1] (RowIndex = 1, ColIndex =1)

Image 2

Figure 2: BackColor of Row 2 (RowIndex = 2, ColIndex = -1)

Introduction

If we want to set the row or cell backcolor in a custom DataGridView control, we may have many methods, such as customizing the column, using DefaultCellStyle, etc. Here, a method by way of .NET events will be introduced.

The steps include: define the CellBackColorEventArgs class, customize the DataGridView control with the SetCellBackColor event, override the OnCellPainting method, and draw the cell BackColor if the event has been subscribed.

1. Define an EventArgs Class

C#
public class CellBackColorEventArgs : EventArgs
{
    private int m_RowIndex;
    private int m_ColIndex;
    private Color m_BackColor = Color.Empty;

    public CellBackColorEventArgs(int row, int col)
    {
        m_RowIndex = row;
        m_ColIndex = col;
    }

    public int RowIndex
    { 
        get { return m_RowIndex; } 
    }
    
    public int ColIndex
    { 
        get { return m_ColIndex; } 
    }
    
    public Color BackColor
    {
        get { return m_BackColor; }
        set { m_BackColor = value; }
    }
}

The CellBackColorEventArgs class has two public readonly properties: RowIndex and ColIndex, which are used to denote the current cell in the OnCellPainting event of DataGridView. The public property BackColor has the default value Color.Empty denoting no BackColor to be assigned to this cell.

2. Customize a DataGridView Control

C#
public class CustomDataGridView : DataGridView
{
    public CustomDataGridView() { }

    [Description("Set cell background color, Colindex -1 denotes any col.")]
    public event EventHandler<CellBackColorEventArgs> SetCellBackColor;

    private void DrawCellBackColor(DataGridViewCellPaintingEventArgs e)
    {
        if ((e.State & DataGridViewElementStates.Selected) == 
                DataGridViewElementStates.Selected)
        {
            base.OnCellPainting(e);
            return;
        }

        if (this.SetCellBackColor == null)  // this event has no subscriber
        {
            base.OnCellPainting(e);
            return;
        }

        CellBackColorEventArgs ee = new CellBackColorEventArgs
                (e.RowIndex, e.ColumnIndex);
        this.SetCellBackColor(this, ee);  //  get the EventArgs ee

        if (ee.BackColor == Color.Empty)  // if subscriber does not set BackColor
        {
            base.OnCellPainting(e);
            return;
        }

        using (SolidBrush fillBrush = new SolidBrush(ee.BackColor))
        using (Pen gridPenColor = new Pen(this.GridColor))
        {
            Rectangle rect1 =  
        new Rectangle(e.CellBounds.Location, e.CellBounds.Size);
            Rectangle rect2 = 
        new Rectangle(e.CellBounds.Location, e.CellBounds.Size);
            
            rect1.X -= 1;
            rect1.Y -= 1;

            rect2.Width -= 1;
            rect2.Height -= 1;

            // must draw border for grid scrolling horizontally 
            e.Graphics.DrawRectangle(gridPenColor, rect1);  

            e.Graphics.FillRectangle(fillBrush, rect2);
        }

        e.PaintContent(e.CellBounds);  // output cell text
        e.Handled = true;
    }

    protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
    {
        if (e.RowIndex >= 0 && e.ColumnIndex >= 0)  // data cell
        {
            this.DrawCellBackColor(e);
        }
        else
        {
            base.OnCellPainting(e);
        }
    }
}

The code above has three contents:

  • public event EventHandler<CellBackColorEventArgs> SetCellBackColor defines an event using generic delegate EventHandler<T>.
  • DrawCellBackColor is used to draw a cell.
  • Overrides OnCellPainting and uses DrawCellBackColor when the current cell is the data cell; that is e.RowIndex >=0 and e.ColIndex >= 0.

Key Skills

The first skill is to capture the event SetCellBackColor before drawing the cell, and see if it has a subscription. If the event has been subscribed, then test the return parameter (see code below), and if ee.BackColor is not Color.Empty which denotes the BackColor is assigned to the current cell, draw the cell including the border, background color, and content.

C#
if (this.SetCellBackColor == null)  // this event has no subscriber
{
    base.OnCellPainting(e);
    return;
}

CellBackColorEventArgs ee = new CellBackColorEventArgs(e.RowIndex, e.ColumnIndex);
this.SetCellBackColor(this, ee);  //  get the eventArgs

if (ee.BackColor == Color.Empty)  // if subscriber does not set BackColor
{
     base.OnCellPainting(e);
     return;
}

Another thing is that we can set the row or cell by using an event. If we give -1 to the col index that we want to change the BackColor, we will set the whole row BackColor as in the usage example below.

Using the Code

After unzipping CustomDataGridView.zip, we can double click the solution file CustomDataGridView.sln to view the test project if we have Visual Studio 2005/2008, or we can run the file CustomDataGridView.exe in the \bin folder to test the control.

The Windows application example code is shown below:

C#
private void customDataGridView1_SetCellBackColor
        (object sender, CellBackColorEventArgs e)
{
     if (e.RowIndex != (int)nu_RowIndex.Value)  // not current row
     {
        return;
     }
            
     if((int)nu_ColIndex.Value == -1)  // denote any col, i.e. the whole row
     {
        e.BackColor = Color.LightCoral;
     }
     else if ((int)nu_ColIndex.Value == e.ColIndex)  // only current cell
     {
        e.BackColor = Color.LightCoral;
     }
}

private void nu_RowIndex_ValueChanged(object sender, EventArgs e)
{
      customDataGridView1.Refresh();
}
private void nu_ColIndex_ValueChanged(object sender, EventArgs e)
{
      customDataGridView1.Refresh();
}

The objects nu_RowIndex and nu_ColIndex are NumericUpDown controls, and nu_RowIndex.Value is the row index we want to change BackColor, and nu_ColIndex.Value is the col index.

Three Usage Notes

  • The row index that we want to change BackColor must be the same as CellBackColorEventArgs e.RowIndex
  • We can set the whole row BackColor if the col index is -1 and the row index is equal to e.RowIndex.
  • We will set the cell BackColor if the col index and row index are the same as e.ColIndex and e.RowIndex.

Conclusion

We can set the row or cell BackColor in our custom DataGridView control by way of .NET events, and we found this method can be applied to many other cases such as merging cells, setting a cell to be readonly, etc..

You can view the Chinese contents that I wrote at http://download.csdn.net/source/612515 (only demo and no source code).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)