Export (0) Print
Expand All
5 out of 7 rated this helpful - Rate this topic

How to: Customize Cells and Columns in the Windows Forms DataGridView Control by Extending Their Behavior and Appearance 

The DataGridView control provides a number of ways to customize its appearance and behavior using properties, events, and companion classes. Occasionally, you may have requirements for your cells that go beyond what these features can provide. You can create your own custom DataGridViewCell class to provide extended functionality.

You create a custom DataGridViewCell class by deriving from the DataGridViewCell base class or one of its derived classes. Although you can display any type of cell in any type of column, you will typically also create a custom DataGridViewColumn class specialized for displaying your cell type. Column classes derive from DataGridViewColumn or one of its derived types.

In the following code example, you will create a custom cell class called DataGridViewRolloverCell that detects when the mouse enters and leaves the cell boundaries. While the mouse is within the cell's bounds, an inset rectangle is drawn. This new type derives from DataGridViewTextBoxCell and behaves in all other respects as its base class. The companion column class is called DataGridViewRolloverColumn.

To use these classes, create a form containing a DataGridView control, add one or more DataGridViewRolloverColumn objects to the Columns collection, and populate the control with rows containing values.

NoteNote

This example will not work correctly if you add empty rows. Empty rows are created, for example, when you add rows to the control by setting the RowCount property. This is because the rows added in this case are automatically shared, which means that DataGridViewRolloverCell objects are not instantiated until you click on individual cells, thereby causing the associated rows to become unshared.

Because this type of cell customization requires unshared rows, it is not appropriate for use with large data sets. For more information about row sharing, see Best Practices for Scaling the Windows Forms DataGridView Control.

NoteNote

When you derive from DataGridViewCell or DataGridViewColumn and add new properties to the derived class, be sure to override the Clone method to copy the new properties during cloning operations. You should also call the base class's Clone method so that the properties of the base class are copied to the new cell or column.

To customize cells and columns in the DataGridView control

  1. Derive a new cell class, called DataGridViewRolloverCell, from the DataGridViewTextBoxCell type.

    public class DataGridViewRolloverCell : DataGridViewTextBoxCell
    {
    ...}
    
    
  2. Override the Paint method in the DataGridViewRolloverCell class. In the override, first call the base class implementation, which handles the hosted text box functionality. Then use the control's PointToClient method to transform the cursor position (in screen coordinates) to the DataGridView client area's coordinates. If the mouse coordinates fall within the bounds of the cell, draw the inset rectangle.

    protected override void Paint(
        Graphics graphics,
        Rectangle clipBounds,
        Rectangle cellBounds,
        int rowIndex,
        DataGridViewElementStates cellState,
        object value,
        object formattedValue,
        string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // Call the base class method to paint the default cell appearance.
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState,
            value, formattedValue, errorText, cellStyle,
            advancedBorderStyle, paintParts);
    
        // Retrieve the client location of the mouse pointer.
        Point cursorPosition =
            this.DataGridView.PointToClient(Cursor.Position);
    
        // If the mouse pointer is over the current cell, draw a custom border.
        if (cellBounds.Contains(cursorPosition))
        {
            Rectangle newRect = new Rectangle(cellBounds.X + 1,
                cellBounds.Y + 1, cellBounds.Width - 4,
                cellBounds.Height - 4);
            graphics.DrawRectangle(Pens.Red, newRect);
        }
    }
    
    
  3. Override the OnMouseEnter and OnMouseLeave methods in the DataGridViewRolloverCell class to force cells to repaint themselves when the mouse pointer enters or leaves them.

    // Force the cell to repaint itself when the mouse pointer enters it.
    protected override void OnMouseEnter(int rowIndex)
    {
        this.DataGridView.InvalidateCell(this);
    }
    
    // Force the cell to repaint itself when the mouse pointer leaves it.
    protected override void OnMouseLeave(int rowIndex)
    {
        this.DataGridView.InvalidateCell(this);
    }
    
    
  4. Derive a new class, called DataGridViewRolloverCellColumn, from the DataGridViewColumn type. In the constructor, assign a new DataGridViewRolloverCell object to its CellTemplate property.

    public class DataGridViewRolloverCellColumn : DataGridViewColumn
    {
        public DataGridViewRolloverCellColumn()
        {
            this.CellTemplate = new DataGridViewRolloverCell();
        }
    }
    
    

Example

The complete code example includes a small test form that demonstrates the behavior of the custom cell type.

using System;
using System.Drawing;
using System.Windows.Forms;

class Form1 : Form
{
    [STAThreadAttribute()]
    public static void Main()
    {
        Application.Run(new Form1());
    }

    public Form1()
    {
        DataGridView dataGridView1 = new DataGridView();
        DataGridViewRolloverCellColumn col =
            new DataGridViewRolloverCellColumn();
        dataGridView1.Columns.Add(col);
        dataGridView1.Rows.Add(new string[] { "" });
        dataGridView1.Rows.Add(new string[] { "" });
        dataGridView1.Rows.Add(new string[] { "" });
        dataGridView1.Rows.Add(new string[] { "" });
        this.Controls.Add(dataGridView1);
        this.Text = "DataGridView rollover-cell demo";
    }
}

public class DataGridViewRolloverCell : DataGridViewTextBoxCell
{
    protected override void Paint(
        Graphics graphics,
        Rectangle clipBounds,
        Rectangle cellBounds,
        int rowIndex,
        DataGridViewElementStates cellState,
        object value,
        object formattedValue,
        string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // Call the base class method to paint the default cell appearance.
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState,
            value, formattedValue, errorText, cellStyle,
            advancedBorderStyle, paintParts);

        // Retrieve the client location of the mouse pointer.
        Point cursorPosition =
            this.DataGridView.PointToClient(Cursor.Position);

        // If the mouse pointer is over the current cell, draw a custom border.
        if (cellBounds.Contains(cursorPosition))
        {
            Rectangle newRect = new Rectangle(cellBounds.X + 1,
                cellBounds.Y + 1, cellBounds.Width - 4,
                cellBounds.Height - 4);
            graphics.DrawRectangle(Pens.Red, newRect);
        }
    }

    // Force the cell to repaint itself when the mouse pointer enters it.
    protected override void OnMouseEnter(int rowIndex)
    {
        this.DataGridView.InvalidateCell(this);
    }

    // Force the cell to repaint itself when the mouse pointer leaves it.
    protected override void OnMouseLeave(int rowIndex)
    {
        this.DataGridView.InvalidateCell(this);
    }

}

public class DataGridViewRolloverCellColumn : DataGridViewColumn
{
    public DataGridViewRolloverCellColumn()
    {
        this.CellTemplate = new DataGridViewRolloverCell();
    }
}

Compiling the Code

See Also

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.