C# DataGridViewの使い方完全ガイド|表示・追加・削除・ソート・データバインドの悩みを解決
はじめに
C#でWindowsフォームアプリを作るとき、一覧表形式でデータを表示・編集したい場面は非常に多くあります。たとえば、顧客一覧、商品マスタ、売上一覧、在庫管理、検索結果、設定画面などです。
そのような画面でよく使われるのが、C# DataGridViewです。
DataGridViewを使うと、表形式でデータを表示できるだけでなく、行の追加、削除、編集、ソート、検索、フィルター、データベース連携なども実装できます。一方で、初心者にとっては「データが表示されない」「行が追加できない」「DataSourceを設定したらRows.Addできない」「ソートや更新が反映されない」といった悩みも起きやすいコントロールです。
この記事では、C# DataGridViewの基本的な使い方から、データ追加・削除・編集、データバインド、ソート、検索、見た目のカスタマイズ、イベント処理、実務で使える応用テクニックまで、順番に解説します。
1. C# DataGridViewとは?できることと使う場面
1-1. DataGridViewの基本概要
DataGridViewは、C#のWindowsフォームアプリで表形式のデータを表示するためのコントロールです。System.Windows.Forms.DataGridViewクラスとして提供されており、フォーム上に配置して使用します。
Excelのように行と列で構成された画面を作ることができ、セル単位で値を表示したり、ユーザーに直接入力させたりできます。
主に次のような用途で使われます。
C#// DataGridViewに列と行を追加する基本例
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Rows.Add(1, "山田太郎");
dataGridView1.Rows.Add(2, "佐藤花子");
このように、少ないコードで表形式のデータを表示できます。
1-2. DataGridViewでできる主な操作
C# DataGridViewでは、次のような操作ができます。
・データの一覧表示
・行の追加
・行の削除
・セルの編集
・列ヘッダー名の変更
・列幅や行高さの変更
・文字色や背景色の変更
・チェックボックス列の表示
・コンボボックス列の表示
・列ヘッダークリックによるソート
・DataTableやListとのデータバインド
・データベースの検索結果表示
・CSVの読み込みや出力
単なる表表示だけでなく、業務アプリの入力画面や管理画面にも使える便利なコントロールです。
1-3. ListView・GridView・DataTableとの違い
DataGridViewと似た名前のものに、ListView、GridView、DataTableがあります。それぞれ役割が異なります。
ListViewは、一覧表示に向いているコントロールです。ファイル一覧やアイコン付きリストのような表示に適しています。ただし、Excelのような表形式の入力や編集にはDataGridViewのほうが向いています。
GridViewは、ASP.NET Webフォームなどで使われることが多い表表示用のコントロールです。Windowsフォームで使う場合はDataGridViewが一般的です。
DataTableは画面部品ではなく、メモリ上に表形式のデータを保持するためのクラスです。DataGridViewにDataTableをバインドすると、DataTableの内容を画面上に表示できます。
C#DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Rows.Add(1, "山田太郎");
table.Rows.Add(2, "佐藤花子");
dataGridView1.DataSource = table;
つまり、DataTableはデータを持つ側、DataGridViewはデータを表示する側と考えるとわかりやすいです。
1-4. WindowsフォームアプリでDataGridViewが使われる場面
DataGridViewは、特に業務系Windowsアプリでよく使われます。
たとえば、次のような画面です。
・顧客一覧画面
・商品マスタ管理画面
・売上明細画面
・在庫一覧画面
・社員一覧画面
・検索結果表示画面
・CSV編集画面
・データベース管理画面
データを一覧表示し、必要に応じて追加・編集・削除する画面では、DataGridViewが非常に役立ちます。
1-5. 初心者がDataGridViewでつまずきやすいポイント
C# DataGridViewで初心者がつまずきやすいポイントは、主に次のとおりです。
・列を追加しないまま行を追加してしまう
・DataSource設定後にRows.Addしようとしてエラーになる
・選択行がないのに削除しようとしてエラーになる
・セルの値がnullで例外になる
・Listをバインドしたが更新が反映されない
・列が自動生成されて意図しない表示になる
・ソートやフィルターのやり方がわからない
DataGridViewは便利ですが、直接行を操作する方法と、DataSourceを使う方法では考え方が異なります。ここを理解すると、エラーを減らしやすくなります。
2. C# DataGridViewの基本的な使い方
2-1. DataGridViewをフォームに配置する方法
Visual StudioでWindowsフォームアプリを作成したら、ツールボックスからDataGridViewをフォームにドラッグ&ドロップします。
配置したDataGridViewには、通常 dataGridView1 のような名前が付けられます。プロパティウィンドウから名前を変更することもできます。
コードから動的に配置することもできます。
C#DataGridView dgv = new DataGridView();
dgv.Name = "dataGridView1";
dgv.Location = new Point(10, 10);
dgv.Size = new Size(500, 300);
this.Controls.Add(dgv);
通常はデザイナーで配置し、コードで列やデータを設定する方法がわかりやすいです。
2-2. 列を追加する方法
DataGridViewに手動で列を追加するには、Columns.Addを使います。
C#dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
第1引数は列の名前、第2引数は画面に表示されるヘッダー名です。
列名はプログラムから参照するときに使います。
C#dataGridView1.Rows[0].Cells["Name"].Value = "田中一郎";
2-3. 行を追加する方法
列を追加したあと、Rows.Addで行を追加できます。
C#dataGridView1.Rows.Add(1, "山田太郎", 30);
dataGridView1.Rows.Add(2, "佐藤花子", 25);
dataGridView1.Rows.Add(3, "鈴木次郎", 40);
列数と値の数が合っていない場合でも追加はできますが、意図しない空白セルができることがあります。基本的には列数に合わせて値を指定しましょう。
2-4. セルに値を表示する方法
特定のセルに値を設定するには、行番号と列番号を指定します。
C#dataGridView1.Rows[0].Cells[0].Value = 1;
dataGridView1.Rows[0].Cells[1].Value = "山田太郎";
dataGridView1.Rows[0].Cells[2].Value = 30;
列名を使って指定することもできます。
C#dataGridView1.Rows[0].Cells["Name"].Value = "山田太郎";
列番号で指定するよりも、列名で指定したほうがコードの意味がわかりやすくなります。
2-5. ヘッダー名を設定する方法
列を追加したあとでヘッダー名を変更する場合は、HeaderTextを使います。
C#dataGridView1.Columns["Id"].HeaderText = "社員ID";
dataGridView1.Columns["Name"].HeaderText = "氏名";
dataGridView1.Columns["Age"].HeaderText = "年齢";
データバインド時に自動生成された列のヘッダー名を変更したい場合にも使えます。
C#dataGridView1.Columns["ProductName"].HeaderText = "商品名";
dataGridView1.Columns["Price"].HeaderText = "価格";
2-6. 実行時にDataGridViewへデータを表示するサンプルコード
フォーム読み込み時にDataGridViewへデータを表示する例です。
C#private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
dataGridView1.Rows.Add(1, "山田太郎", 30);
dataGridView1.Rows.Add(2, "佐藤花子", 25);
dataGridView1.Rows.Add(3, "鈴木次郎", 40);
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
AutoSizeColumnsModeを設定すると、列幅をDataGridViewの幅に合わせて調整できます。
3. DataGridViewにデータを追加・編集・削除する方法
3-1. 行を追加する方法
未バインドのDataGridViewに行を追加する場合は、Rows.Addを使います。
C#private void buttonAdd_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Add(4, "高橋美咲", 28);
}
ユーザーが画面上で新しい行を追加できるようにするには、AllowUserToAddRowsを有効にします。
C#dataGridView1.AllowUserToAddRows = true;
ただし、DataSourceを設定している場合は、DataGridViewのRows.Addではなく、バインド元のDataTableやListに追加するのが基本です。
C#DataTable table = (DataTable)dataGridView1.DataSource;
table.Rows.Add(4, "高橋美咲", 28);
3-2. 選択行を削除する方法
選択されている行を削除するには、SelectedRowsを使います。
C#private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("削除する行を選択してください。");
return;
}
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}
}
IsNewRowは、ユーザー入力用の空行かどうかを判定するプロパティです。新規行を削除しようとするとエラーになることがあるため、チェックしておくと安全です。
DataSourceを使っている場合は、DataGridViewの行を直接削除するのではなく、バインド元から削除します。
C#DataRowView rowView = dataGridView1.CurrentRow.DataBoundItem as DataRowView;
if (rowView != null)
{
rowView.Delete();
}
3-3. セルの値を編集する方法
セルの値をコードから変更するには、CellsのValueを設定します。
C#dataGridView1.Rows[0].Cells["Name"].Value = "変更後の名前";
選択中のセルを変更する場合は、CurrentCellを使います。
C#if (dataGridView1.CurrentCell != null)
{
dataGridView1.CurrentCell.Value = "新しい値";
}
ユーザーに編集させたい場合は、DataGridViewのReadOnlyをfalseにします。
C#dataGridView1.ReadOnly = false;
列単位で編集可否を設定することもできます。
C#dataGridView1.Columns["Id"].ReadOnly = true;
dataGridView1.Columns["Name"].ReadOnly = false;
3-4. 編集不可にする方法
DataGridView全体を編集不可にするには、ReadOnlyをtrueにします。
C#dataGridView1.ReadOnly = true;
行の追加や削除も禁止したい場合は、次のように設定します。
C#dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
一覧表示専用のDataGridViewにしたい場合は、次の設定がよく使われます。
C#dataGridView1.ReadOnly = true;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
3-5. 行追加や削除でよくあるエラーと対処法
DataGridViewで行追加や削除をするときによくあるエラーのひとつが、DataSource設定後にRows.Addを使ってしまうケースです。
C#dataGridView1.DataSource = table;
dataGridView1.Rows.Add(1, "山田太郎"); // エラーになることがある
DataSourceを使っている場合は、DataGridViewではなくDataTableなどのデータ元に追加します。
C#table.Rows.Add(1, "山田太郎");
削除時によくあるエラーは、選択行がないのに削除しようとするケースです。
C#if (dataGridView1.CurrentRow == null)
{
return;
}
また、ユーザー入力用の新規行を削除しようとしてエラーになることもあります。
C#if (!dataGridView1.CurrentRow.IsNewRow)
{
dataGridView1.Rows.Remove(dataGridView1.CurrentRow);
}
3-6. 追加・編集・削除の実用サンプルコード
以下は、テキストボックスの入力値をDataGridViewに追加し、選択行を編集・削除するサンプルです。
C#private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.AllowUserToAddRows = false;
}
private void buttonAdd_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Add(textBoxId.Text, textBoxName.Text, textBoxAge.Text);
}
private void buttonUpdate_Click(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null)
{
MessageBox.Show("編集する行を選択してください。");
return;
}
DataGridViewRow row = dataGridView1.CurrentRow;
row.Cells["Id"].Value = textBoxId.Text;
row.Cells["Name"].Value = textBoxName.Text;
row.Cells["Age"].Value = textBoxAge.Text;
}
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null || dataGridView1.CurrentRow.IsNewRow)
{
MessageBox.Show("削除する行を選択してください。");
return;
}
dataGridView1.Rows.Remove(dataGridView1.CurrentRow);
}
4. DataGridViewでデータバインドする方法
4-1. データバインドとは何か
データバインドとは、DataGridViewにDataTableやListなどのデータを関連付けて、自動的に表示する仕組みです。
手動でRows.Addを繰り返す方法よりも、データ量が多い場合やデータベースと連携する場合に便利です。
C#dataGridView1.DataSource = table;
DataSourceにデータを設定すると、DataGridViewはその内容を自動的に表形式で表示します。
4-2. DataTableをDataGridViewに表示する方法
DataTableをDataGridViewに表示する基本例です。
C#private void Form1_Load(object sender, EventArgs e)
{
DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));
table.Rows.Add(1, "山田太郎", 30);
table.Rows.Add(2, "佐藤花子", 25);
table.Rows.Add(3, "鈴木次郎", 40);
dataGridView1.DataSource = table;
}
DataTableを使うと、フィルターやソートも行いやすくなります。
4-3. ListをDataGridViewに表示する方法
クラスのListをDataGridViewに表示することもできます。
C#public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
C#private void Form1_Load(object sender, EventArgs e)
{
List<Person> people = new List<Person>
{
new Person { Id = 1, Name = "山田太郎", Age = 30 },
new Person { Id = 2, Name = "佐藤花子", Age = 25 },
new Person { Id = 3, Name = "鈴木次郎", Age = 40 }
};
dataGridView1.DataSource = people;
}
Listを使うと、プロパティ名が列名として表示されます。
ただし、通常のList<T>では、追加や削除をしてもDataGridViewに自動反映されない場合があります。画面更新を重視するなら、BindingList<T>を使うと便利です。
C#BindingList<Person> people = new BindingList<Person>();
people.Add(new Person { Id = 1, Name = "山田太郎", Age = 30 });
dataGridView1.DataSource = people;
4-4. BindingSourceを使ってバインドする方法
BindingSourceは、DataGridViewとデータの間に入る仲介役です。並び替え、現在行の取得、データ更新などを扱いやすくできます。
C#BindingSource bindingSource = new BindingSource();
DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));
table.Rows.Add(1, "山田太郎", 30);
table.Rows.Add(2, "佐藤花子", 25);
bindingSource.DataSource = table;
dataGridView1.DataSource = bindingSource;
BindingSourceを使うと、現在選択されているデータを取得しやすくなります。
C#DataRowView current = bindingSource.Current as DataRowView;
if (current != null)
{
string name = current["Name"].ToString();
MessageBox.Show(name);
}
4-5. SQL Serverなどデータベースのデータを表示する方法
SQL ServerのデータをDataGridViewに表示する場合は、データベースから取得した結果をDataTableに入れて、DataSourceに設定する方法がよく使われます。
C#using System.Data;
using System.Data.SqlClient;
C#private void LoadData()
{
string connectionString = "Data Source=.;Initial Catalog=SampleDb;Integrated Security=True";
string sql = "SELECT Id, Name, Age FROM Employees";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, connection))
{
DataTable table = new DataTable();
adapter.Fill(table);
dataGridView1.DataSource = table;
}
}
検索条件を指定する場合は、SQL文にWHERE句を追加します。
C#string sql = "SELECT Id, Name, Age FROM Employees WHERE Name LIKE @Name";
パラメータを使う場合は、SqlCommandと組み合わせてSQLインジェクションを防ぐことが重要です。
4-6. データバインド時に列名や表示順を変更する方法
DataSourceを設定すると、自動的に列が作られます。列名を変更したい場合は、DataSource設定後にHeaderTextを変更します。
C#dataGridView1.Columns["Id"].HeaderText = "社員ID";
dataGridView1.Columns["Name"].HeaderText = "氏名";
dataGridView1.Columns["Age"].HeaderText = "年齢";
表示順を変更するには、DisplayIndexを使います。
C#dataGridView1.Columns["Name"].DisplayIndex = 0;
dataGridView1.Columns["Id"].DisplayIndex = 1;
dataGridView1.Columns["Age"].DisplayIndex = 2;
特定の列を非表示にするには、Visibleをfalseにします。
C#dataGridView1.Columns["Id"].Visible = false;
列を自動生成したくない場合は、AutoGenerateColumnsをfalseにして、自分で列を定義します。
C#dataGridView1.AutoGenerateColumns = false;
DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn();
nameColumn.DataPropertyName = "Name";
nameColumn.HeaderText = "氏名";
nameColumn.Name = "Name";
dataGridView1.Columns.Add(nameColumn);
dataGridView1.DataSource = people;
4-7. データバインドで表示されない・更新されない原因
データバインドで表示されない場合は、次の点を確認します。
・DataSourceにnullを設定していないか
・Listのクラスにpublicプロパティがあるか
・フィールドではなくプロパティになっているか
・AutoGenerateColumnsがfalseなのに列を定義していないか
・DataPropertyNameがプロパティ名と一致しているか
・DataTableに行が入っているか
たとえば、Listをバインドする場合、次のようなフィールドだけのクラスはうまく表示されません。
C#public class Person
{
public int Id;
public string Name;
}
DataGridViewに表示するには、プロパティにします。
C#public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
Listの追加・削除が反映されない場合は、BindingList<T>やBindingSource.ResetBindings(false)を使います。
C#bindingSource.ResetBindings(false);
5. DataGridViewのソート・検索・フィルター機能
5-1. 列ヘッダークリックでソートする方法
DataGridViewでは、列ヘッダーをクリックするとソートできる場合があります。
手動で列を作成している場合は、列のSortModeを設定します。
C#dataGridView1.Columns["Name"].SortMode = DataGridViewColumnSortMode.Automatic;
DataTableをバインドしている場合は、列ヘッダークリックによるソートが使いやすいです。
C#dataGridView1.DataSource = table;
ただし、List<T>をそのままバインドした場合は、期待通りにソートできないことがあります。その場合は、DataTableやBindingSourceを使う方法を検討しましょう。
5-2. プログラムから並び替える方法
コードからDataGridViewを並び替えるには、Sortメソッドを使います。
C#dataGridView1.Sort(
dataGridView1.Columns["Name"],
System.ComponentModel.ListSortDirection.Ascending
);
降順にしたい場合は、Descendingを指定します。
C#dataGridView1.Sort(
dataGridView1.Columns["Age"],
System.ComponentModel.ListSortDirection.Descending
);
DataTableを使っている場合は、DataViewのSortを使う方法もあります。
C#DataView view = table.DefaultView;
view.Sort = "Age DESC";
dataGridView1.DataSource = view;
5-3. DataViewを使ってフィルターする方法
DataTableの内容を条件で絞り込みたい場合は、DataViewのRowFilterを使います。
C#DataView view = table.DefaultView;
view.RowFilter = "Age >= 30";
dataGridView1.DataSource = view;
文字列で絞り込む場合は、LIKEを使います。
C#view.RowFilter = "Name LIKE '%山田%'";
DataViewを使うと、DataGridViewに表示するデータだけを簡単にフィルターできます。
5-4. テキストボックス入力で検索する方法
検索用のTextBoxに入力された文字を使って、DataGridViewの表示を絞り込む例です。
C#private DataTable table;
private void Form1_Load(object sender, EventArgs e)
{
table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));
table.Rows.Add(1, "山田太郎", 30);
table.Rows.Add(2, "佐藤花子", 25);
table.Rows.Add(3, "山田花子", 28);
dataGridView1.DataSource = table;
}
private void textBoxSearch_TextChanged(object sender, EventArgs e)
{
string keyword = textBoxSearch.Text.Replace("'", "''");
DataView view = table.DefaultView;
view.RowFilter = $"Name LIKE '%{keyword}%'";
}
ユーザー入力をRowFilterに使う場合、シングルクォートをエスケープすることが重要です。
5-5. 数値・日付・文字列で絞り込む方法
数値で絞り込む場合は、次のように書きます。
C#table.DefaultView.RowFilter = "Age >= 30";
文字列で絞り込む場合は、シングルクォートで囲みます。
C#table.DefaultView.RowFilter = "Name = '山田太郎'";
部分一致検索をする場合は、LIKEを使います。
C#table.DefaultView.RowFilter = "Name LIKE '%山田%'";
日付で絞り込む場合は、日付列の型をDateTimeにしておくと扱いやすくなります。
C#table.DefaultView.RowFilter = "OrderDate >= #2026/01/01#";
複数条件を指定する場合は、ANDやORを使います。
C#table.DefaultView.RowFilter = "Age >= 30 AND Name LIKE '%山田%'";
5-6. ソートやフィルターができないときの原因と対処法
ソートやフィルターができない場合は、DataGridViewそのものではなく、バインド元のデータ構造が原因であることが多いです。
DataTableを使っている場合は、DataViewのSortやRowFilterが使えます。
C#table.DefaultView.Sort = "Name ASC";
table.DefaultView.RowFilter = "Age >= 30";
一方、List<T>をそのままDataSourceに設定している場合、DataViewのようなRowFilterは使えません。検索やフィルターを実装するには、LINQで絞り込んだ結果を再バインドする方法があります。
C#var filtered = people
.Where(p => p.Name.Contains(textBoxSearch.Text))
.ToList();
dataGridView1.DataSource = filtered;
ソートやフィルターを多用する画面では、DataTableやBindingSourceを使うと実装しやすくなります。
6. DataGridViewの見た目をカスタマイズする方法
6-1. 列幅・行高さを変更する方法
列幅を指定するには、Widthを使います。
C#dataGridView1.Columns["Name"].Width = 150;
すべての列幅を自動調整するには、AutoSizeColumnsModeを使います。
C#dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
行の高さを変更するには、RowTemplate.Heightを使います。
C#dataGridView1.RowTemplate.Height = 30;
すでに表示されている行に対して個別に高さを変えることもできます。
C#dataGridView1.Rows[0].Height = 40;
6-2. セルの文字色・背景色を変更する方法
セルの見た目は、DefaultCellStyleで変更できます。
C#dataGridView1.DefaultCellStyle.ForeColor = Color.Black;
dataGridView1.DefaultCellStyle.BackColor = Color.White;
選択時の色も変更できます。
C#dataGridView1.DefaultCellStyle.SelectionBackColor = Color.LightBlue;
dataGridView1.DefaultCellStyle.SelectionForeColor = Color.Black;
交互に行の色を変えると、一覧が見やすくなります。
C#dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;
6-3. ヘッダーのデザインを変更する方法
ヘッダーの背景色や文字色を変更するには、ColumnHeadersDefaultCellStyleを使います。
C#dataGridView1.EnableHeadersVisualStyles = false;
dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
dataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("Meiryo", 10, FontStyle.Bold);
EnableHeadersVisualStylesがtrueのままだと、OSのテーマが優先されて色が反映されないことがあります。ヘッダーの色を変える場合は、falseにしておくのがポイントです。
6-4. 日付・数値・金額の表示形式を変更する方法
日付や数値の表示形式は、DefaultCellStyle.Formatで指定できます。
日付を年月日形式で表示する例です。
C#dataGridView1.Columns["OrderDate"].DefaultCellStyle.Format = "yyyy/MM/dd";
数値を3桁区切りで表示する例です。
C#dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";
金額のように右寄せで表示したい場合は、Alignmentも設定します。
C#dataGridView1.Columns["Price"].DefaultCellStyle.Alignment =
DataGridViewContentAlignment.MiddleRight;
6-5. チェックボックス・コンボボックス列を追加する方法
チェックボックス列を追加するには、DataGridViewCheckBoxColumnを使います。
C#DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "IsSelected";
checkColumn.HeaderText = "選択";
dataGridView1.Columns.Add(checkColumn);
コンボボックス列を追加するには、DataGridViewComboBoxColumnを使います。
C#DataGridViewComboBoxColumn comboColumn = new DataGridViewComboBoxColumn();
comboColumn.Name = "Category";
comboColumn.HeaderText = "カテゴリ";
comboColumn.Items.Add("食品");
comboColumn.Items.Add("家電");
comboColumn.Items.Add("日用品");
dataGridView1.Columns.Add(comboColumn);
データバインド時にコンボボックス列を使う場合は、DataPropertyNameも設定します。
C#comboColumn.DataPropertyName = "Category";
6-6. 条件に応じてセルの色を変える方法
条件によってセルの色を変更したい場合は、CellFormattingイベントを使います。
C#private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Stock")
{
if (e.Value != null && int.TryParse(e.Value.ToString(), out int stock))
{
if (stock <= 10)
{
e.CellStyle.BackColor = Color.LightPink;
e.CellStyle.ForeColor = Color.DarkRed;
}
}
}
}
在庫数が少ない場合に背景色を変えるなど、実務でもよく使うテクニックです。
6-7. ユーザーが見やすい表にするための設定
DataGridViewを見やすくするには、次のような設定がよく使われます。
C#dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.ReadOnly = true;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.RowHeadersVisible = false;
dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;
一覧表示専用の画面では、行全体を選択できるようにし、不要な行追加や行削除を禁止すると使いやすくなります。
7. DataGridViewのイベント処理
7-1. セルクリック時の処理
セルがクリックされたときの処理は、CellClickイベントで実装します。
C#private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
{
return;
}
string name = dataGridView1.Rows[e.RowIndex].Cells["Name"].Value?.ToString();
MessageBox.Show(name);
}
ヘッダーがクリックされた場合、RowIndexは-1になるため、チェックしておくことが重要です。
7-2. 行選択時の処理
行を選択したときに、選択行の内容をテキストボックスへ表示する例です。
C#private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null)
{
return;
}
textBoxId.Text = dataGridView1.CurrentRow.Cells["Id"].Value?.ToString();
textBoxName.Text = dataGridView1.CurrentRow.Cells["Name"].Value?.ToString();
textBoxAge.Text = dataGridView1.CurrentRow.Cells["Age"].Value?.ToString();
}
入力フォームとDataGridViewを連携させる場合によく使います。
7-3. セル編集後の処理
セルの編集が完了したあとに処理を行うには、CellEndEditイベントを使います。
C#private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
string columnName = dataGridView1.Columns[e.ColumnIndex].Name;
object value = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
Console.WriteLine($"{columnName} が {value} に変更されました。");
}
編集後に合計金額を再計算したい場合などに使えます。
7-4. 値変更時の処理
セルの値が変更されたときは、CellValueChangedイベントを使います。
C#private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
{
return;
}
Console.WriteLine("セルの値が変更されました。");
}
チェックボックス列の場合、クリックしただけではすぐに値変更イベントが発生しないことがあります。その場合は、CurrentCellDirtyStateChangedで変更を確定します。
C#private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
7-5. 入力チェックを行う方法
セル入力時のチェックには、CellValidatingイベントを使います。
C#private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Age")
{
if (!int.TryParse(e.FormattedValue.ToString(), out int age))
{
MessageBox.Show("年齢は数値で入力してください。");
e.Cancel = true;
}
}
}
e.Cancel = trueにすると、入力が確定されず、ユーザーは修正を求められます。
7-6. よく使うDataGridViewイベント一覧
DataGridViewでよく使うイベントは次のとおりです。
CellClickは、セルがクリックされたときに使います。CellDoubleClickは、セルがダブルクリックされたときに使います。SelectionChangedは、選択行や選択セルが変わったときに使います。CellEndEditは、セル編集が終了したときに使います。CellValueChangedは、セルの値が変更されたときに使います。CellValidatingは、セル入力の検証に使います。CellFormattingは、表示時の書式や色を変更するときに使います。DataErrorは、データバインドやコンボボックス列でエラーが起きたときに使います。
特に、実務ではCellClick、SelectionChanged、CellValidating、CellFormatting、DataErrorを使う場面が多いです。
8. DataGridViewでよくある悩みと解決方法
8-1. データが表示されない
データが表示されない場合は、まずDataSourceに正しくデータが入っているか確認します。
C#MessageBox.Show(table.Rows.Count.ToString());
Listを使っている場合は、クラスのメンバーがpublicプロパティになっているか確認します。
C#public string Name { get; set; }
また、AutoGenerateColumnsをfalseにしている場合は、列のDataPropertyNameが正しく設定されている必要があります。
C#nameColumn.DataPropertyName = "Name";
8-2. 行が追加できない
DataSourceを設定しているDataGridViewに対して、Rows.Addを使うとエラーになることがあります。
C#dataGridView1.Rows.Add(...);
この場合は、DataGridViewではなく、バインド元に追加します。
C#DataTable table = (DataTable)dataGridView1.DataSource;
table.Rows.Add(1, "山田太郎", 30);
Listを使う場合は、BindingList<T>を使うと追加が反映されやすくなります。
C#BindingList<Person> people = new BindingList<Person>();
dataGridView1.DataSource = people;
people.Add(new Person { Id = 1, Name = "山田太郎", Age = 30 });
8-3. 削除処理でエラーが出る
削除処理でエラーが出る場合は、選択行が存在するか、新規行ではないかを確認します。
C#if (dataGridView1.CurrentRow == null)
{
return;
}
if (dataGridView1.CurrentRow.IsNewRow)
{
return;
}
dataGridView1.Rows.Remove(dataGridView1.CurrentRow);
DataSourceを使っている場合は、バインド元のデータを削除するのが基本です。
C#DataRowView rowView = dataGridView1.CurrentRow.DataBoundItem as DataRowView;
if (rowView != null)
{
rowView.Delete();
}
8-4. Nullや空白セルでエラーが出る
セルの値がnullの場合、ToString()を直接呼び出すとエラーになることがあります。
C#string name = dataGridView1.CurrentRow.Cells["Name"].Value.ToString();
安全に取得するには、null条件演算子を使います。
C#string name = dataGridView1.CurrentRow.Cells["Name"].Value?.ToString() ?? "";
DataTableでは、値がDBNull.Valueになっている場合もあります。
C#object value = row["Name"];
if (value == DBNull.Value)
{
value = "";
}
Nullや空白があり得る画面では、必ずチェックを入れるようにしましょう。
8-5. ソートできない
ソートできない場合は、列のSortModeやDataSourceの種類を確認します。
C#dataGridView1.Columns["Name"].SortMode = DataGridViewColumnSortMode.Automatic;
DataTableを使っている場合は、DataViewのSortを使うと確実です。
C#table.DefaultView.Sort = "Name ASC";
List<T>を使っている場合は、LINQで並び替えて再バインドする方法があります。
C#dataGridView1.DataSource = people.OrderBy(p => p.Name).ToList();
8-6. データベース更新が反映されない
データベースを更新したのにDataGridViewに反映されない場合、画面上のDataTableが古いままになっている可能性があります。
更新後に再取得することで反映できます。
C#private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
DataTableに対して変更しただけでは、データベースへ自動保存されない点にも注意が必要です。データベースに反映するには、UPDATE、INSERT、DELETEなどのSQLを実行する必要があります。
8-7. 列が自動生成されて意図しない表示になる
DataSourceを設定すると、デフォルトでは列が自動生成されます。そのため、表示したくないプロパティまで列として表示されることがあります。
自分で列を定義したい場合は、AutoGenerateColumnsをfalseにします。
C#dataGridView1.AutoGenerateColumns = false;
そのうえで、表示したい列だけ追加します。
C#DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn();
nameColumn.HeaderText = "氏名";
nameColumn.DataPropertyName = "Name";
nameColumn.Name = "Name";
dataGridView1.Columns.Add(nameColumn);
8-8. 選択行やセルの取得方法がわからない
現在選択されている行を取得するには、CurrentRowを使います。
C#DataGridViewRow row = dataGridView1.CurrentRow;
選択行のセル値を取得するには、次のように書きます。
C#string name = dataGridView1.CurrentRow.Cells["Name"].Value?.ToString();
現在選択されているセルを取得するには、CurrentCellを使います。
C#object value = dataGridView1.CurrentCell.Value;
複数行選択を扱う場合は、SelectedRowsを使います。
C#foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
string name = row.Cells["Name"].Value?.ToString();
}
9. DataGridViewを実務で使うための応用テクニック
9-1. CSVファイルをDataGridViewに読み込む方法
CSVファイルを読み込んでDataGridViewに表示するには、File.ReadAllLinesで行を読み込み、DataTableに変換する方法があります。
C#private void LoadCsv(string filePath)
{
DataTable table = new DataTable();
string[] lines = File.ReadAllLines(filePath, Encoding.UTF8);
if (lines.Length == 0)
{
return;
}
string[] headers = lines[0].Split(',');
foreach (string header in headers)
{
table.Columns.Add(header);
}
for (int i = 1; i < lines.Length; i++)
{
string[] values = lines[i].Split(',');
table.Rows.Add(values);
}
dataGridView1.DataSource = table;
}
ただし、この方法はカンマを含む文字列やダブルクォートを厳密には処理できません。実務で複雑なCSVを扱う場合は、CSV解析用のライブラリを使うと安全です。
9-2. DataGridViewの内容をCSV出力する方法
DataGridViewの内容をCSVに出力する例です。
C#private void SaveCsv(string filePath)
{
StringBuilder sb = new StringBuilder();
List<string> headers = new List<string>();
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
headers.Add(column.HeaderText);
}
sb.AppendLine(string.Join(",", headers));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow)
{
continue;
}
List<string> values = new List<string>();
foreach (DataGridViewCell cell in row.Cells)
{
string value = cell.Value?.ToString() ?? "";
value = value.Replace("\"", "\"\"");
values.Add($"\"{value}\"");
}
sb.AppendLine(string.Join(",", values));
}
File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8);
}
セルの値をダブルクォートで囲み、値の中にあるダブルクォートをエスケープしておくと、CSVとして扱いやすくなります。
9-3. Excelのような表を作る方法
DataGridViewをExcelのように使いやすくするには、コピー&ペースト、行選択、列幅調整、交互色などを設定します。
C#dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView1.AllowUserToResizeColumns = true;
dataGridView1.AllowUserToResizeRows = true;
コピー機能を有効にすると、選択したセルをExcelに貼り付けやすくなります。
C#private void buttonCopy_Click(object sender, EventArgs e)
{
DataObject dataObject = dataGridView1.GetClipboardContent();
if (dataObject != null)
{
Clipboard.SetDataObject(dataObject);
}
}
9-4. 入力フォームとDataGridViewを連携する方法
実務では、上部に入力欄、下部にDataGridViewを配置する画面がよくあります。
選択行の内容をテキストボックスに表示し、編集ボタンで更新する形です。
C#private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null)
{
return;
}
textBoxId.Text = dataGridView1.CurrentRow.Cells["Id"].Value?.ToString();
textBoxName.Text = dataGridView1.CurrentRow.Cells["Name"].Value?.ToString();
textBoxAge.Text = dataGridView1.CurrentRow.Cells["Age"].Value?.ToString();
}
private void buttonUpdate_Click(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null)
{
return;
}
dataGridView1.CurrentRow.Cells["Name"].Value = textBoxName.Text;
dataGridView1.CurrentRow.Cells["Age"].Value = textBoxAge.Text;
}
この構成にすると、一覧から選択して詳細を編集する画面を作りやすくなります。
9-5. マスターデータ管理画面を作る方法
商品マスタや社員マスタのような管理画面では、DataGridViewとデータベースを組み合わせることが多いです。
基本的な流れは次のとおりです。
画面読み込み時にデータベースから一覧を取得する
DataTableに入れてDataGridViewに表示する
追加ボタンでINSERTを実行する
更新ボタンでUPDATEを実行する
削除ボタンでDELETEを実行する
処理後に一覧を再読み込みする
例として、削除後に再読み込みする処理は次のようになります。
C#private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.CurrentRow == null)
{
return;
}
int id = Convert.ToInt32(dataGridView1.CurrentRow.Cells["Id"].Value);
DeleteEmployee(id);
LoadData();
}
一覧表示とデータベース更新を分けて考えると、保守しやすいコードになります。
9-6. 大量データ表示時のパフォーマンス対策
DataGridViewに大量データを表示すると、画面表示が遅くなることがあります。数万件以上のデータを扱う場合は、次のような対策が必要です。
まず、必要なデータだけ取得します。データベースから全件取得せず、検索条件やページングを使って件数を絞ります。
SQLSELECT Id, Name, Age
FROM Employees
ORDER BY Id
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY
次に、列幅の自動調整を使いすぎないようにします。
C#dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
AutoSizeColumnsMode.AllCellsは便利ですが、大量データでは遅くなることがあります。
大量データを本格的に扱う場合は、VirtualModeの利用も検討します。
C#dataGridView1.VirtualMode = true;
dataGridView1.RowCount = 100000;
VirtualModeでは、表示に必要なセルの値だけをイベントで渡すため、大量データでも軽く表示しやすくなります。ただし、実装は少し複雑になるため、まずはデータ件数を絞る設計を優先するとよいでしょう。
まとめ
C# DataGridViewは、Windowsフォームアプリで表形式のデータを扱うための非常に便利なコントロールです。データの表示、追加、削除、編集、ソート、検索、フィルター、データバインド、見た目のカスタマイズまで、業務アプリに必要な多くの機能を実装できます。
基本的な使い方では、列を追加してRows.Addで行を表示します。より実務的な画面では、DataTable、List、BindingSource、データベースなどをDataSourceに設定してデータバインドする方法がよく使われます。
特に重要なのは、未バインドのDataGridViewと、DataSourceを使ったDataGridViewでは操作方法が異なるという点です。DataSourceを使っている場合、行の追加や削除はDataGridView本体ではなく、DataTableやBindingListなどのバインド元に対して行います。
また、ソートやフィルターを使いたい場合はDataTableとDataViewが便利です。見た目を整えたい場合は、列幅、行高さ、セル色、ヘッダー、表示形式などを調整すると、ユーザーにとって見やすい画面になります。
C# DataGridViewを正しく使えるようになると、一覧画面、検索画面、マスタ管理画面、CSV編集画面、データベース管理画面など、さまざまなWindowsフォームアプリを効率よく作成できます。基本操作とデータバインドの違いを理解し、エラーが起きやすいポイントを押さえながら実装していきましょう。

