Vorgehensweise: Anpassen von Zellen und Spalten im DataGridView-Steuerelement in Windows Forms durch Erweitern des Aussehens und Verhaltens

Das DataGridView-Steuerelement bietet eine Reihe von Möglichkeiten, sein Aussehen und Verhalten mithilfe von Eigenschaften, Ereignissen und Assistentenklassen anzupassen. Gelegentlich haben Sie möglicherweise Anforderungen an die Zellen, die über die Möglichkeiten hinausgehen, die diese Funktionen bieten können. Sie können Ihre eigene benutzerdefinierte DataGridViewCell-Klasse erstellen, um erweiterte Funktionalität bereitzustellen.

Sie erstellen eine benutzerdefinierte DataGridViewCell-Klasse, indem Sie von der DataGridViewCell-Basisklasse oder einer ihrer abgeleiteten Klassen ableiten. Auch wenn Sie in jedem Spaltentyp jeden Zellentyp anzeigen können, erstellen Sie in der Regel außerdem eine benutzerdefinierte DataGridViewColumn-Klasse speziell zum Anzeigen des Zellentyps. Spaltenklassen werden von DataGridViewColumn oder einem davon abgeleiteten Typ abgeleitet.

Im folgenden Codebeispiel erstellen Sie eine benutzerdefinierte Zellenklasse namens DataGridViewRolloverCell, die erkennt, wann sich der Mauszeiger innerhalb bzw. außerhalb der Zellenumgrenzung befindet. Wenn sich der Mauszeiger innerhalb der Zellenumgrenzungen befindet, wird ein abgesenktes Rechteck gezeichnet. Dieser neue Typ leitet sich von DataGridViewTextBoxCell ab und verhält sich in jeder anderen Hinsicht wie seine Basisklasse. Die Assistentenspaltenklasse heißt DataGridViewRolloverColumn.

Erstellen Sie zum Verwenden dieser Klassen ein Formular mit einem DataGridView-Steuerelement, fügen Sie der Columns-Auflistung ein oder mehrere DataGridViewRolloverColumn-Objekte hinzu, und füllen Sie das Steuerelement mit Zeilen, die Werte enthalten.

Hinweis

Dieses Beispiel funktioniert nicht ordnungsgemäß, wenn Sie leere Zeilen hinzufügen. Leere Zeilen werden beispielsweise erstellt, wenn Sie dem Steuerelement Zeilen hinzufügen, indem Sie die RowCount-Eigenschaft festlegen. Der Grund dafür ist, dass die in diesem Fall hinzugefügten Zeilen automatisch freigegeben werden. Das heißt, dass DataGridViewRolloverCell-Objekte erst instanziiert werden, wenn Sie auf einzelne Zellen klicken und somit die Freigabe der zugeordneten Zeilen aufheben.

Da bei dieser Art der Zellenanpassung nicht freigegebene Zeilen benötigt werden, eignet sie sich nicht für große DataSets. Weitere Informationen zum Freigeben von Zeilen finden Sie unter Empfohlene Vorgehensweisen für das Skalieren des DataGridView-Steuerelements in Windows Forms.

Hinweis

Wenn Sie aus DataGridViewCell oder DataGridViewColumn ableiten und der abgeleiteten Klasse neue Eigenschaften hinzufügen, müssen Sie die Clone-Methode überschreiben, damit die neuen Eigenschaften bei Klonvorgängen kopiert werden. Außerdem sollten Sie die Clone-Methode der Basisklasse aufrufen, damit die Eigenschaften der Basisklasse in die neue Zelle oder Spalte kopiert werden.

So passen Sie Zellen und Spalten im DataGridView-Steuerelement an

  1. Leiten Sie eine neue Zellenklasse namens DataGridViewRolloverCell vom DataGridViewTextBoxCell-Typ ab.

    public class DataGridViewRolloverCell : DataGridViewTextBoxCell
    {
    
    Public Class DataGridViewRolloverCell
        Inherits DataGridViewTextBoxCell
    
    }
    
    End Class
    
  2. Überschreiben Sie die Paint -Methode in der DataGridViewRolloverCell -Klasse. Rufen Sie in der Überschreibung zuerst die Basisklassenimplementierung auf, die die gehosteten Textfeldfunktionen behandelt. Verwenden Sie dann die PointToClient-Methode des Steuerelements, um die Cursorposition (in Bildschirmkoordinaten) in die Koordinaten des DataGridView-Clientbereichs umzuwandeln. Wenn die Mauskoordinaten innerhalb der Zellenumgrenzung liegen, zeichnen Sie das abgesenkte Rechteck.

    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);
        }
    }
    
    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
    
  3. Überschreiben Sie die OnMouseEnter-Methode und die OnMouseLeave-Methode in der DataGridViewRolloverCell-Klasse, um Zellen dazu zu zwingen, sich selbst neu zu zeichnen, wenn der Mauszeiger darüber bewegt wird.

    // 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);
    }
    
    ' 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
    
  4. Leiten Sie eine neue Klasse namens DataGridViewRolloverCellColumn vom DataGridViewColumn-Typ ab. Weisen Sie im Konstruktor ein neues DataGridViewRolloverCell-Objekt seiner CellTemplate-Eigenschaft zu.

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

Beispiel

Das vollständige Codebeispiel umfasst ein kleines Testformular, das das Verhalten des benutzerdefinierten Zellentyps veranschaulicht.

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

Kompilieren des Codes

Für dieses Beispiel benötigen Sie Folgendes:

  • Verweise auf die Assemblys "System", "System.Windows.Forms" und "System.Drawing".

Weitere Informationen