注意:DataGridViewコントロールは、.NET Framework 2.0で新しく追加されました。
行ヘッダーに文字列を表示する方法は、こちらで紹介しました。そこで紹介したように、行ヘッダーセルのValueプロパティに行番号を指定する方法があります。ただしこの方法では、行が削除されたり、並び替えが行われたりした時に、その都度Valueプロパティを設定しなおす必要があります。
このような方法以外に、DataGridViewのRowPostPaintやCellPaintingイベントハンドラなどを使ってヘッダーに文字列を描画する方法があります。ここでは、CellPaintingやRowPostPaintイベントを使用して行ヘッダーに行番号を表示する方法を紹介します。
CellPaintingイベントハンドラでは、DataGridViewCellPaintingEventArgsオブジェクトのColumnIndexとRowIndexプロパティにより描画するセルの位置を知ることができますが、列ヘッダーセルの場合はRowIndexは-1に、行ヘッダーセルの場合はColumnIndexが-1になります。
以下に例を示します。ここでは行ヘッダーセルに行番号を縦方向の中央に、黒色で描画しています。
'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
//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メソッドではなく、このようにしています。
「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?」の方法では、隣のセルまでも描画されてしまいます)。これを防ぐには、行ヘッダーの幅に収まるように文字列を描画するようにします。さらに、行ヘッダーが表示されている時のみ描画するようにします。
'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
//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イベントについて詳しくは、こちらをご覧ください。