다음을 통해 공유


방법: Windows Forms DataGridView 컨트롤에서 동작 및 모양을 확장하여 셀과 열 사용자 지정

업데이트: 2007년 11월

DataGridView 컨트롤은 속성, 이벤트 및 자매 클래스를 사용하여 해당 모양과 동작을 사용자 지정할 수 있는 여러 가지 방법을 제공합니다. 이러한 기능에서 제공할 수 있는 범위를 넘어서는 기능이 셀에 필요한 경우가 있습니다. 사용자는 자신만의 고유한 사용자 지정 DataGridViewCell 클래스를 만들어서 확장된 기능을 제공할 수 있습니다.

DataGridViewCell 기본 클래스 또는 이 클래스의 파생 클래스 중 하나에서 파생하여 사용자 지정 DataGridViewCell 클래스를 만들 수 있습니다. 모든 형식의 열에 모든 형식의 셀을 표시할 수는 있지만 일반적으로 셀 형식을 표시하기 위해 특수화된 사용자 지정 DataGridViewColumn 클래스를 만듭니다. 열 클래스는 DataGridViewColumn 또는 해당 파생 형식 중 하나에서 파생됩니다.

다음 코드 예제에서는 마우스가 셀 경계선으로 들어가고 나오는 시기를 감지하는 DataGridViewRolloverCell이라는 사용자 지정 셀 클래스를 만듭니다. 마우스가 셀 경계선 내에 있는 동안 셀 테두리 사각형이 그려집니다. 이 새 형식은 DataGridViewTextBoxCell에서 파생되며 다른 모든 요소에서 이 형식의 기본 클래스처럼 동작합니다. 자매 열 클래스는 DataGridViewRolloverColumn이라고 합니다.

이러한 클래스를 사용하려면 DataGridView 컨트롤을 포함하는 폼을 만들고, Columns 컬렉션에 하나 이상의 DataGridViewRolloverColumn 개체를 추가하고, 값을 포함하는 행으로 컨트롤을 채웁니다.

참고:

빈 행을 추가하는 경우에는 이 예제가 올바르게 작동하지 않습니다. 예를 들어, RowCount 속성을 설정하여 컨트롤에 행을 추가하면 빈 행이 만들어집니다. 그 이유는 이 경우 추가된 행이 자동으로 공유되기 때문입니다. 즉, DataGridViewRolloverCell 개체는 개별 셀을 클릭할 때까지 인스턴스화되지 않으므로 연관된 행은 공유되지 않습니다.

이러한 셀 사용자 지정 형식은 공유되지 않는 행을 필요로 하므로 큰 데이터 집합에 사용하기에 적합하지 않습니다. 행 공유에 대한 자세한 내용은 Windows Forms DataGridView 컨트롤의 크기를 조정하는 최선의 방법을 참조하십시오.

참고:

DataGridViewCell 또는 DataGridViewColumn에서 클래스를 파생하고 파생 클래스에 새 속성을 추가하는 경우에는 복제 작업 중에 새 속성을 복사하도록 Clone 메서드를 재정의해야 합니다. 또한 기본 클래스의 속성이 새 셀 또는 열에 복사되도록 기본 클래스의 Clone 메서드를 호출해야 합니다.

DataGridView 컨트롤의 셀 및 열을 사용자 지정하려면

  1. DataGridViewTextBoxCell 형식에서 DataGridViewRolloverCell이라는 새 셀 클래스를 파생합니다.

    Public Class DataGridViewRolloverCell
        Inherits DataGridViewTextBoxCell
    
    
    ...
    
    
    End Class
    
    public class DataGridViewRolloverCell : DataGridViewTextBoxCell
    {
    
    
    ...
    
    
    }
    
  2. DataGridViewRolloverCell 클래스의 Paint 메서드를 재정의합니다. 재정의 시 우선 기본 클래스 구현을 호출합니다. 그러면 호스팅된 텍스트 상자 기능이 처리됩니다. 그런 다음 컨트롤의 PointToClient 메서드를 사용하여 커서 위치(화면 좌표)를 DataGridView 클라이언트 영역의 좌표로 변환합니다. 마우스 좌표가 셀의 경계선 내에 위치하면 음각 사각형이 그려집니다.

    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. DataGridViewRolloverCell 클래스의 OnMouseEnterOnMouseLeave 메서드를 재정의하여 마우스 포인터가 셀에 들어가거나 셀에서 나올 때 셀이 강제로 다시 그려지도록 합니다.

    ' 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. DataGridViewColumn 형식에서 DataGridViewRolloverCellColumn이라는 새 클래스를 파생합니다. 생성자에서 새 DataGridViewRolloverCell 개체를 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();
        }
    }
    

예제

전체 코드 예제에는 사용자 지정 셀 형식의 동작을 보여 주는 간단한 테스트가 포함되어 있습니다.

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

코드 컴파일

이 예제에는 다음 사항이 필요합니다.

  • System, System.Windows.Forms 및 System.Drawing 어셈블리에 대한 참조

Visual Basic 또는 Visual C#의 명령줄에서 이 예제를 빌드하는 방법에 대한 자세한 내용은 명령줄에서 빌드(Visual Basic) 또는 csc.exe를 사용한 명령줄 빌드를 참조하십시오. Visual Studio에서 코드를 새 프로젝트에 붙여넣어 이 예제를 빌드할 수도 있습니다.

참고 항목

개념

DataGridView 컨트롤 아키텍처(Windows Forms)

Windows Forms DataGridView 컨트롤의 열 형식

Windows Forms DataGridView 컨트롤의 크기를 조정하는 최선의 방법

참조

DataGridView

DataGridViewCell

DataGridViewColumn

기타 리소스

Windows Forms DataGridView 컨트롤 사용자 지정