Comment : personnaliser les cellules et les colonnes du contrôle DataGridView Windows Forms en étendant leur comportement et leur apparence

Mise à jour : novembre 2007

Le contrôle DataGridView offre plusieurs façons de personnaliser son apparence et son comportement à l'aide de propriétés, d'événements et de classes auxiliaires. Parfois, vous pouvez avoir une configuration requise pour vos cellules qui vont au-delà de ce que ces fonctionnalités peuvent fournir. Vous pouvez créer votre propre classe DataGridViewCell personnalisée pour fournir des fonctionnalités étendues.

Vous créez une classe DataGridViewCell personnalisée en dérivant de la classe de base DataGridViewCell ou une de ses classes dérivées. Bien que vous puissiez afficher tout type de cellule dans tout type de colonne, vous créerez en général également une classe DataGridViewColumn personnalisée spécialisée pour l'affichage votre type de cellule. Les classes Column dérivent de DataGridViewColumn ou d'un de ses types dérivés.

Dans l'exemple de code suivant, vous créerez une classe de cellule personnalisée appelée DataGridViewRolloverCell, qui détecte quand la souris se trouve dans ou hors des limites d'une cellule. Lorsque la souris se trouve dans les limites de la cellule, un rectangle intercalaire est dessiné. Ce nouveau type dérive de DataGridViewTextBoxCell et se comporte à tous égards comme sa classe de base. La classe Column auxiliaire est appelée DataGridViewRolloverColumn.

Pour utiliser ces classes, créez un formulaire qui contient un contrôle DataGridView, ajoutez un ou plusieurs objets DataGridViewRolloverColumn à la collection Columns et remplissez le contrôle avec des lignes qui contiennent des valeurs.

Remarque :

Cet exemple ne fonctionnera pas correctement si vous ajoutez des lignes vides. Par exemple, des lignes vides sont créées lorsque vous ajoutez des lignes au contrôle en définissant la propriété RowCount. C'est parce que les lignes ajoutées dans ce cas sont partagées automatiquement, qui signifie que les objets DataGridViewRolloverCell ne sont instanciés jusqu'une fois que vous cliquez sur les cellules individuelles, faisant ainsi en sorte que les lignes associées deviennent non partagées.

Dans la mesure où ce type de personnalisation de cellule requiert des lignes non partagées, il n'est pas approprié pour une utilisation avec de grands groupes de données. Pour plus d'informations sur le partage de lignes, consultez Méthodes conseillées pour la mise à l'échelle du contrôle DataGridView Windows Forms.

Remarque :

Lorsque vous effectuez une dérivation à partir de DataGridViewCell ou DataGridViewColumn et ajoutez de nouvelles propriétés à la classe dérivée, veillez à substituer la méthode Clone pour copier les nouvelles propriétés au cours des opérations de clonage. Vous devez également appeler la méthode Clone de la classe de base afin que les propriétés de cette classe soient copiées dans la nouvelle cellule ou colonne.

Pour personnaliser des cellules et des colonnes dans le contrôle DataGridView

  1. Dérivez une nouvelle classe de cellule, appelée DataGridViewRolloverCell, du type DataGridViewTextBoxCell.

    Public Class DataGridViewRolloverCell
        Inherits DataGridViewTextBoxCell
    
    
    ...
    
    
    End Class
    
    public class DataGridViewRolloverCell : DataGridViewTextBoxCell
    {
    
    
    ...
    
    
    }
    
  2. Substituez la méthode Paint de la classe DataGridViewRolloverCell. Dans la substitution, appelez en premier l'implémentation de classe de base qui gère les fonctionnalités de zone de texte hébergées. Puis utilisez la méthode PointToClient du contrôle pour transformer la position du curseur (dans les coordonnées d'écran) aux coordonnées de la zone cliente DataGridView. Si les coordonnées de la souris se trouvent dans les limites de la cellule, dessinez le rectangle intercalaire.

    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. Substituez les méthodes OnMouseEnter et OnMouseLeave dans la classe DataGridViewRolloverCell pour forcer des cellules à se repeindre lorsque le pointeur de la souris entre dans ces cellules ou les quitte.

    ' 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. Dérivez une nouvelle classe, appelée DataGridViewRolloverCellColumn, du type DataGridViewColumn. Dans le constructeur, assignez un nouvel objet DataGridViewRolloverCell à sa propriété 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();
        }
    }
    

Exemple

L'exemple de code complet inclut un petit formulaire de test qui montre le comportement du type de cellule personnalisé.

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

Compilation du code

Cet exemple nécessite les éléments suivants :

  • Références aux assemblys System, System.Windows.Forms et System.Drawing.

Pour plus d'informations sur la génération de cet exemple à partir de la ligne de commande pour Visual Basic ou Visual C#, consultez Génération à partir de la ligne de commande (Visual Basic) ou Génération à partir de la ligne de commande avec csc.exe. Vous pouvez aussi générer cet exemple dans Visual Studio en collant le code dans un nouveau projet.

Voir aussi

Concepts

Architecture du contrôle DataGridView (Windows Forms)

Types de colonnes dans le contrôle DataGridView Windows Forms

Méthodes conseillées pour la mise à l'échelle du contrôle DataGridView Windows Forms

Référence

DataGridView

DataGridViewCell

DataGridViewColumn

Autres ressources

Personnalisation du contrôle DataGridView Windows Forms