DataGridView:列ヘッダーに画像アイコンを表示(サンプルあり)

📋 目次(クリックで展開)

DataGridView の一覧画面を構築する際、特定の列ヘッダーに「鍵マーク」、「スターマーク」などの画像アイコンを配置して、視認性を高めたい場合があります。

DataGridView の標準機能では、列ヘッダーのテキスト(HeaderText)には文字列のみを指定できる仕様となっていますが、セルの描画イベントを利用することで、ヘッダー内の指定した位置に画像を描画できます。

今回は、列ヘッダーに文字列とアイコン画像を並べて表示する実装方法を紹介します。

列ヘッダーに画像を描画する仕組み

列ヘッダーに画像を表示するには、DataGridView の CellPainting イベントを利用します。

このイベントは、セルが画面に描画されるたびに発生する処理です。イベントハンドラ内で「描画対象が列ヘッダーであるか(RowIndex-1 であるか)」を判定し、条件に一致する場合に対象の列に対して e.Graphics.DrawImage メソッドを使用して画像を描画します。

実装コード

以下は、DataTable をデータソースとしてバインドし、1番目の列(Code列)のヘッダーにアイコン画像を描画するコード例です。

テスト用に、プロジェクト内に icon.png などの画像ファイルを用意するか、既存の画像パスに書き換えてお試しください。

Form1.cs
using System.Data;
namespace DataGridView_HeaderWithImage
{
public partial class Form1 : Form
{
private DataTable _dataTable = new DataTable();
private Image? _headerIcon;
public Form1()
{
InitializeComponent();
InitializeDataGridView();
}
private void InitializeDataGridView()
{
// テスト用アイコン画像の準備(※実行ファイルと同じフォルダに icon.png を配置)
if (File.Exists("icon.png"))
{
_headerIcon = Image.FromFile("icon.png");
}
// テスト用データの準備
// 💡 後の章で解説する文字の重なりを防ぐため、ヘッダーテキストの先頭にスペースを3つ入れています
_dataTable.Columns.Add(" Code", typeof(string));
_dataTable.Columns.Add("Name", typeof(string));
_dataTable.Rows.Add("P001", "ノートパソコン");
_dataTable.Rows.Add("P002", "USBメモリ");
dataGridView1.DataSource = _dataTable;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
// セル描画イベントを購読
dataGridView1.CellPainting += DataGridView1_CellPainting;
}
/// <summary>
/// セルの描画が行われるときに発生するイベント
/// </summary>
private void DataGridView1_CellPainting(object? sender, DataGridViewCellPaintingEventArgs e)
{
// 列ヘッダー行(RowIndex が -1)かつ、対象の列(0番目の列)であり、画像が存在するか確認
if (e.RowIndex == -1 && e.ColumnIndex == 0 && _headerIcon != null)
{
// 1. 背景や枠線など、文字(Foreground)以外の部分を先に標準描画する
e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground);
// 2. アイコンを描画する座標を計算
// セルの左端から5ピクセル、上下中央に配置する計算式です
int iconWidth = 16;
int iconHeight = 16;
int x = e.CellBounds.Left + 5;
int y = e.CellBounds.Top + (e.CellBounds.Height - iconHeight) / 2;
// 3. 計算した位置にアイコン画像を描画
e.Graphics?.DrawImage(_headerIcon, x, y, iconWidth, iconHeight);
// 4. 文字部分(Foreground)を後から上書き描画する
e.Paint(e.CellBounds, DataGridViewPaintParts.ContentForeground);
// 5. システム側の標準描画処理が重複して走らないように完了通知を出す
e.Handled = true;
}
}
}
}

サンプルアプリケーション

DataGridView_HeaderWithImage.zip
※ サンプルアプリケーションは、.NET 10 をターゲットに作成しています。

実行結果

Code 列の左側に、画像が配置されていることが分かります。

留意すべき注意点と実装の背景

列ヘッダーへの画像描画を安定して動作させるために把握しておくとよい点が2つあります。

テキストとアイコン画像が重なる問題の対策

単に e.Graphics.DrawImage を実行するだけでは、元々設定されている HeaderText の文字列の開始位置と画像の位置が重なってしまい、文字が潰れてしまいます。

これを回避する簡易的で実務的な方法が、サンプルコード内にある「ヘッダーテキストの先頭にあらかじめスペース(空白文字)を挿入しておく方法」です。

// 文字の先頭にスペースを入れて、画像が表示されるための隙間を確保する
_dataTable.Columns.Add(" Code", typeof(string));

テキストの先頭に数文字分のスペースを設けることで、描画される文字の位置が右側にずれます。その空いた隙間(セルの左端)を狙って画像を描画することで、複雑な文字描画ロジックを自前で計算することなく、横並びに配置できます。

画像オブジェクトの管理と描画負荷への配慮

CellPainting イベントは、マウスがセルの上を通過したり、画面がスクロールされたりするたびに高頻度で呼び出されます。

そのため、以下のようにイベントハンドラの中で毎回画像をファイルから読み込むような処理は避ける必要があります。

// ❌ 描画負荷が著しく高くなるコード例
e.Graphics.DrawImage(Image.FromFile("icon.png"), x, y);

イベントの中でファイルI/Oを発生させると、画面のスクロールが重くなったり、メモリ消費量が増大したりする原因になります。サンプルコードのように、フォームの初期化時(InitializeDataGridView)に一度だけ Image オブジェクトを読み込んでメンバ変数(_headerIcon)に保持し、イベント内ではそれを再利用する構成が適しています。

まとめ

今回は、DataGridView の列ヘッダーに画像アイコンを埋め込んで表示する方法について解説しました。

標準では文字列しか表示できないヘッダー領域ですが、CellPainting イベントで標準描画(e.Paint)のタイミングを制御することで、任意の画像を描画できます。

  • RowIndex == -1 の条件で列ヘッダーの描画タイミングを捉える
  • HeaderText の先頭にスペースを入れて画像用の領域を確保する
  • 描画イベント内でのファイル読み込みは避け、事前に読み込んだ変数を再利用する

これらの手順を整えることで、システム特有のステータスや属性を視覚的に分かりやすく伝える一覧画面の構築が可能になります。ヘッダーのデザインを調整する際の参考になれば幸いです。


💬 コメント