Compartir a través de


Cómo: Personalizar celdas y columnas en el control DataGridView de formularios Windows Forms ampliando su comportamiento y apariencia

Actualización: noviembre 2007

El control DataGridView proporciona varias maneras de personalizar la apariencia y comportamiento mediante propiedades, eventos y clases complementarias. De vez en cuando, puede tener requisitos para sus celdas que exceden lo que estas características pueden proporcionar. Puede crear su propia clase DataGridViewCell personalizada para proporcionar la funcionalidad ampliada.

Cree una clase DataGridViewCell personalizada que derive de la clase base DataGridViewCell o de una de sus clases derivadas. Aunque pueda mostrar cualquier tipo de celda en cualquier tipo de columna, normalmente también cree una clase DataGridViewColumn personalizada especializada en mostrar el tipo de celda. Las clases de columna derivan de DataGridViewColumn o de uno de sus tipos derivados.

En el ejemplo de código siguiente, creará una clase de celda personalizada llamada DataGridViewRolloverCell que detecta cuándo el mouse (ratón) entra y sale de los límites de la celda. Mientras el mouse está dentro de los límites de la celda, se dibuja un rectángulo de bajorrelieve. Este nuevo tipo deriva de DataGridViewTextBoxCell y se comporta como su clase base. La clase de columna complementaria se denomina DataGridViewRolloverColumn.

Para utilizar estas clases, cree un formulario que contenga un control DataGridView, agregue uno o más objetos DataGridViewRolloverColumn a la colección Columns y rellene el control con filas que contiene valores.

Nota:

Este ejemplo no funcionará correctamente si agrega filas vacías. Por ejemplo, se crean filas vacías cuando agrega filas al control estableciendo la propiedad RowCount. Esto es debido a que las filas agregadas en este caso se comparten de forma automática, lo que significa que no se crean instancias de los objetos DataGridViewRolloverCell hasta que se hace clic en celdas individuales, produciendo por tanto que las filas asociadas no se compartan.

Dado que este tipo de personalización de celda requiere filas no compartidas, no es adecuado su uso con grandes conjuntos de datos. Para obtener más información sobre cómo compartir filas, vea Procedimientos recomendados para ajustar la escala del control DataGridView en formularios Windows Forms.

Nota:

Cuando derive de DataGridViewCell o DataGridViewColumn y agregue nuevas propiedades a la clase derivada, asegúrese de reemplazar el método Clone para copiar las nuevas propiedades durante las operaciones de clonación. También debería llamar al método Clone de la clase base para que las propiedades de esta clase se copien en la nueva celda o columna.

Para personalizar celdas y columnas en el control DataGridView

  1. Derive una nueva clase de celda, denominada DataGridViewRolloverCell, desde el tipo DataGridViewTextBoxCell.

    Public Class DataGridViewRolloverCell
        Inherits DataGridViewTextBoxCell
    
    
    ...
    
    
    End Class
    
    public class DataGridViewRolloverCell : DataGridViewTextBoxCell
    {
    
    
    ...
    
    
    }
    
  2. Reemplace el método Paint en la clase DataGridViewRolloverCell. En la operación de reemplazo, llame primero a la implementación de la clase base, que controla la funcionalidad del cuadro de texto alojado. A continuación, utilice el método PointToClient de control para transformar la posición del cursor (en coordenadas de la pantalla) a las coordenadas del área de cliente DataGridView. Si las coordenadas del mouse se encuentran dentro de los límites de la celda, se dibuja el rectángulo de bajorrelieve.

    Protected Overrides Sub Paint( _
        ByVal graphics As Graphics, _
        ByVal clipBounds As Rectangle, _
        ByVal cellBounds As Rectangle, _
        ByVal rowIndex As Integer, _
        ByVal elementState As DataGridViewElementStates, _
        ByVal value As Object, _
        ByVal formattedValue As Object, _
        ByVal errorText As String, _
        ByVal cellStyle As DataGridViewCellStyle, _
        ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
        ByVal paintParts As DataGridViewPaintParts)
    
        ' Call the base class method to paint the default cell appearance.
        MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, _
            value, formattedValue, errorText, cellStyle, _
            advancedBorderStyle, paintParts)
    
        ' Retrieve the client location of the mouse pointer.
        Dim cursorPosition As Point = _
            Me.DataGridView.PointToClient(Cursor.Position)
    
        ' If the mouse pointer is over the current cell, draw a custom border.
        If cellBounds.Contains(cursorPosition) Then
            Dim newRect As New Rectangle(cellBounds.X + 1, _
                cellBounds.Y + 1, cellBounds.Width - 4, _
                cellBounds.Height - 4)
            graphics.DrawRectangle(Pens.Red, newRect)
        End If
    
    End Sub
    
    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. Reemplace los métodos OnMouseEnter y OnMouseLeave en la clase DataGridViewRolloverCell para forzar a las celdas que volverse a dibujar cuando el puntero del mouse entra o sale de ellas.

    ' Force the cell to repaint itself when the mouse pointer enters it.
    Protected Overrides Sub OnMouseEnter(ByVal rowIndex As Integer)
        Me.DataGridView.InvalidateCell(Me)
    End Sub
    
    ' Force the cell to repaint itself when the mouse pointer leaves it.
    Protected Overrides Sub OnMouseLeave(ByVal rowIndex As Integer)
        Me.DataGridView.InvalidateCell(Me)
    End Sub
    
    // 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 una nueva clase, denominada DataGridViewRolloverCellColumn, desde el tipo DataGridViewColumn. En el constructor, asigne un nuevo objeto DataGridViewRolloverCell a su propiedad CellTemplate.

    Public Class DataGridViewRolloverCellColumn
        Inherits DataGridViewColumn
    
        Public Sub New()
            Me.CellTemplate = New DataGridViewRolloverCell()
        End Sub
    
    End Class
    
    public class DataGridViewRolloverCellColumn : DataGridViewColumn
    {
        public DataGridViewRolloverCellColumn()
        {
            this.CellTemplate = new DataGridViewRolloverCell();
        }
    }
    

Ejemplo

En el ejemplo de código completo se incluye un pequeño formulario de prueba que muestra el comportamiento del tipo de celda personalizado.

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Class Form1
    Inherits Form

    <STAThreadAttribute()> _
    Public Shared Sub Main()
        Application.Run(New Form1())
    End Sub

    Public Sub New()
        Dim dataGridView1 As New DataGridView()
        Dim col As 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() {""})
        Me.Controls.Add(dataGridView1)
        Me.Text = "DataGridView rollover-cell demo"
    End Sub

End Class

Public Class DataGridViewRolloverCell
    Inherits DataGridViewTextBoxCell

    Protected Overrides Sub Paint( _
        ByVal graphics As Graphics, _
        ByVal clipBounds As Rectangle, _
        ByVal cellBounds As Rectangle, _
        ByVal rowIndex As Integer, _
        ByVal elementState As DataGridViewElementStates, _
        ByVal value As Object, _
        ByVal formattedValue As Object, _
        ByVal errorText As String, _
        ByVal cellStyle As DataGridViewCellStyle, _
        ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
        ByVal paintParts As DataGridViewPaintParts)

        ' Call the base class method to paint the default cell appearance.
        MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, _
            value, formattedValue, errorText, cellStyle, _
            advancedBorderStyle, paintParts)

        ' Retrieve the client location of the mouse pointer.
        Dim cursorPosition As Point = _
            Me.DataGridView.PointToClient(Cursor.Position)

        ' If the mouse pointer is over the current cell, draw a custom border.
        If cellBounds.Contains(cursorPosition) Then
            Dim newRect As New Rectangle(cellBounds.X + 1, _
                cellBounds.Y + 1, cellBounds.Width - 4, _
                cellBounds.Height - 4)
            graphics.DrawRectangle(Pens.Red, newRect)
        End If

    End Sub

    ' Force the cell to repaint itself when the mouse pointer enters it.
    Protected Overrides Sub OnMouseEnter(ByVal rowIndex As Integer)
        Me.DataGridView.InvalidateCell(Me)
    End Sub

    ' Force the cell to repaint itself when the mouse pointer leaves it.
    Protected Overrides Sub OnMouseLeave(ByVal rowIndex As Integer)
        Me.DataGridView.InvalidateCell(Me)
    End Sub

End Class

Public Class DataGridViewRolloverCellColumn
    Inherits DataGridViewColumn

    Public Sub New()
        Me.CellTemplate = New DataGridViewRolloverCell()
    End Sub

End Class
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();
    }
}

Compilar el código

Este ejemplo requiere:

  • Referencias a los ensamblados System, System.Windows.Forms y System.Drawing.

Para obtener información acerca de la generación de este ejemplo desde la línea de comandos de Visual Basic o Visual C#, vea Generar desde la línea de comandos (Visual Basic) o Generar la línea de comandos con csc.exe. También puede generar este ejemplo en Visual Studio pegando el código en un proyecto nuevo.

Vea también

Conceptos

Arquitectura del control DataGridView (formularios Windows Forms)

Tipos de columnas en el control DataGridView de formularios Windows Forms

Procedimientos recomendados para ajustar la escala del control DataGridView en formularios Windows Forms

Referencia

DataGridView

DataGridViewCell

DataGridViewColumn

Otros recursos

Personalizar el control DataGridView de formularios Windows Forms