DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DataGridViewの行ヘッダーに行番号を表示する

注意:DataGridViewコントロールは、.NET Framework 2.0で新しく追加されました。

行ヘッダーに文字列を表示する方法は、こちらで紹介しました。そこで紹介したように、行ヘッダーセルのValueプロパティに行番号を指定する方法があります。ただしこの方法では、行が削除されたり、並び替えが行われたりした時に、その都度Valueプロパティを設定しなおす必要があります。

このような方法以外に、DataGridViewのRowPostPaintやCellPaintingイベントハンドラなどを使ってヘッダーに文字列を描画する方法があります。ここでは、CellPaintingやRowPostPaintイベントを使用して行ヘッダーに行番号を表示する方法を紹介します。

CellPaintingイベントハンドラで描画する

CellPaintingイベントハンドラでは、DataGridViewCellPaintingEventArgsオブジェクトのColumnIndexとRowIndexプロパティにより描画するセルの位置を知ることができますが、列ヘッダーセルの場合はRowIndexは-1に、行ヘッダーセルの場合はColumnIndexが-1になります。

以下に例を示します。ここでは行ヘッダーセルに行番号を縦方向の中央に、黒色で描画しています。

VB.NET
コードを隠すコードを選択
'CellPaintingイベントハンドラ
Private Sub DataGridView1_CellPainting(ByVal sender As Object, _
        ByVal e As DataGridViewCellPaintingEventArgs) _
        Handles DataGridView1.CellPainting
    '列ヘッダーかどうか調べる
    If e.ColumnIndex < 0 And e.RowIndex >= 0 Then
        'セルを描画する
        e.Paint(e.ClipBounds, DataGridViewPaintParts.All)

        '行番号を描画する範囲を決定する
        'e.AdvancedBorderStyleやe.CellStyle.Paddingは無視しています
        Dim indexRect As Rectangle = e.CellBounds
        indexRect.Inflate(-2, -2)
        '行番号を描画する
        TextRenderer.DrawText(e.Graphics, _
            (e.RowIndex + 1).ToString(), _
            e.CellStyle.Font, _
            indexRect, _
            e.CellStyle.ForeColor, _
            TextFormatFlags.Right Or TextFormatFlags.VerticalCenter)
        '描画が完了したことを知らせる
        e.Handled = True
    End If
End Sub
C#
コードを隠すコードを選択
//CellPaintingイベントハンドラ
private void DataGridView1_CellPainting(object sender,
    DataGridViewCellPaintingEventArgs e)
{
    //列ヘッダーかどうか調べる
    if (e.ColumnIndex < 0 && e.RowIndex >= 0)
    {
        //セルを描画する
        e.Paint(e.ClipBounds, DataGridViewPaintParts.All);

        //行番号を描画する範囲を決定する
        //e.AdvancedBorderStyleやe.CellStyle.Paddingは無視しています
        Rectangle indexRect = e.CellBounds;
        indexRect.Inflate(-2, -2);
        //行番号を描画する
        TextRenderer.DrawText(e.Graphics,
            (e.RowIndex + 1).ToString(),
            e.CellStyle.Font,
            indexRect,
            e.CellStyle.ForeColor,
            TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
        //描画が完了したことを知らせる
        e.Handled = true;
    }
}
補足:上記の例では、TextRenderer.DrawTextメソッドで文字列を描画しています。DataGridViewは内部ではDrawTextメソッドを使用しているようなので、Graphics.DrawStringメソッドではなく、このようにしています。

RowPostPaintイベントハンドラで描画する

How do I add text to the row header, e.g., a row number, in a DataGridView?(リンク切れのため、Internet Archiveへのリンク)」などでは、RowPostPaintイベントを使用する方法が紹介されています。RowPostPaintイベントハンドラは行の前景を描画するためのイベントです。よって何も考えずにこのイベントハンドラで文字列を描画すると、ヘッダーセルだけでなく、隣のセルにも描画されてしまう可能性があります(「How do I add text to the row header, e.g., a row number, in a DataGridView?」の方法では、隣のセルまでも描画されてしまいます)。これを防ぐには、行ヘッダーの幅に収まるように文字列を描画するようにします。さらに、行ヘッダーが表示されている時のみ描画するようにします。

VB.NET
コードを隠すコードを選択
'RowPostPaintイベントハンドラ
Private Sub DataGridView1_RowPostPaint(ByVal sender As Object, _
        ByVal e As DataGridViewRowPostPaintEventArgs) _
        Handles DataGridView1.RowPostPaint
    Dim dgv As DataGridView = CType(sender, DataGridView)
    If dgv.RowHeadersVisible Then
        '行番号を描画する範囲を決定する
        Dim rect As New Rectangle(e.RowBounds.Left, e.RowBounds.Top, _
            dgv.RowHeadersWidth, e.RowBounds.Height)
        rect.Inflate(-2, -2)
        '行番号を描画する
        TextRenderer.DrawText(e.Graphics, _
            (e.RowIndex + 1).ToString(), _
            e.InheritedRowStyle.Font, _
            rect, _
            e.InheritedRowStyle.ForeColor, _
            TextFormatFlags.Right Or TextFormatFlags.VerticalCenter)
    End If
End Sub
C#
コードを隠すコードを選択
//RowPostPaintイベントハンドラ
private void DataGridView1_RowPostPaint(object sender,
    DataGridViewRowPostPaintEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;
    if (dgv.RowHeadersVisible)
    {
        //行番号を描画する範囲を決定する
        Rectangle rect = new Rectangle(
            e.RowBounds.Left, e.RowBounds.Top,
            dgv.RowHeadersWidth, e.RowBounds.Height);
        rect.Inflate(-2, -2);
        //行番号を描画する
        TextRenderer.DrawText(e.Graphics,
            (e.RowIndex + 1).ToString(),
            e.InheritedRowStyle.Font,
            rect,
            e.InheritedRowStyle.ForeColor,
            TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
    }
}
補足:行の背景を描画するためのイベントは、RowPrePaintイベントです。RowPrePaintおよびRowPostPaintイベントについて詳しくは、こちらをご覧ください。
  • 履歴:
  • 2009/12/25 「行単位でセルの内容を検証する」と「CellValidatingでチェックしても不正な値が入力される」を追加。
  • 2016/5/30 リンク切れを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。