C# DataGridViewの使い方完全ガイド|表示・追加・削除・検索・ソートを初心者向けに解説

はじめに

C#でWindowsフォームアプリケーションを作るとき、表形式のデータを表示・編集する場面はとても多くあります。たとえば、顧客一覧、商品一覧、売上一覧、社員一覧、設定一覧などを画面に表示したい場合、よく使われるのがDataGridViewです。

DataGridViewを使うと、Excelの表のように行と列でデータを表示できます。さらに、行の追加、削除、検索、ソート、セル編集、チェックボックス列、ボタン列、データベース連携など、業務アプリで必要になる機能をまとめて実装できます。

一方で、初心者のうちは「データが表示されない」「選択行の値が取れない」「Rows.Addで追加できない」「検索やソートがうまく動かない」といった悩みも起こりやすいです。

この記事では、C#のDataGridViewの基本的な使い方から、表示、追加、削除、検索、ソート、見た目の調整、イベント、データベース連携、よくあるエラーまで、初心者向けに順番に解説します。

1. C#のDataGridViewとは?できることと基本イメージ

1-1. DataGridViewはWindowsフォームで表形式データを表示・編集するためのコントロール

DataGridViewとは、C#のWindowsフォームアプリケーションで表形式のデータを表示・編集するためのコントロールです。

行と列を持つグリッド形式の画面を簡単に作れるため、一覧画面を作成するときによく使われます。

たとえば、次のようなデータを表示できます。

C#
ID   名前      年齢
1 山田太郎 25
2 佐藤花子 30
3 鈴木一郎 28

このような一覧を画面に表示し、ユーザーが行を選択したり、セルの値を編集したり、ボタン操作で追加・削除したりできます。

DataGridViewは、Windowsフォームアプリケーションで業務システムを作る場合に非常に重要なコントロールです。

1-2. DataGridViewでできること一覧|表示・入力・追加・削除・検索・ソート

DataGridViewでは、主に次のようなことができます。

データの一覧表示、セルの直接編集、行の追加、行の削除、選択行の取得、検索、ソート、列幅の調整、ヘッダー名の変更、チェックボックス列の追加、ボタン列の追加、コンボボックス列の追加、DataTableとの連携、Listやクラスとの連携、データベースとの連携などです。

特に、C#で管理画面や一覧画面を作る場合は、DataGridViewを使うことで効率よく表形式のUIを作成できます。

1-3. ListViewやDataTableとの違い

DataGridViewと混同しやすいものに、ListViewやDataTableがあります。

ListViewは、リスト形式で項目を表示するためのコントロールです。アイコン付きの一覧や簡単なリスト表示には向いていますが、セル編集や複雑な表形式の操作にはDataGridViewの方が向いています。

DataTableは、画面部品ではなく、メモリ上で表形式のデータを扱うためのクラスです。DataGridViewにDataTableを設定すると、DataTableの内容を画面に表示できます。

つまり、DataGridViewは「画面に表示する部品」、DataTableは「データを管理する入れ物」と考えると分かりやすいです。

C#
DataTable table = new DataTable();
dataGridView1.DataSource = table;

このように、DataGridViewとDataTableは一緒に使われることが多いです。

1-4. この記事で作るサンプル画面の完成イメージ

この記事では、次のようなシンプルな一覧画面を想定して解説します。

C#
ID   名前      年齢
1 山田太郎 25
2 佐藤花子 30
3 鈴木一郎 28

画面にはDataGridViewを配置し、ボタンでデータを追加・削除し、TextBoxに入力したキーワードで検索できるようにします。

初心者でも理解しやすいように、まずはセルに直接値を入れる方法から始め、次にDataTableやListを使った実践的な方法へ進みます。

2. DataGridViewを使う準備

2-1. Windowsフォームアプリケーションを作成する

DataGridViewを使うには、まずVisual StudioでWindowsフォームアプリケーションを作成します。

Visual Studioを起動し、「新しいプロジェクトの作成」から「Windows Forms App」を選択します。言語はC#を選びます。

プロジェクトを作成すると、Form1というフォーム画面が表示されます。このフォーム上にDataGridViewを配置して使います。

2-2. フォームにDataGridViewを配置する

フォームにDataGridViewを配置するには、ツールボックスから「DataGridView」を選び、フォーム上にドラッグ&ドロップします。

配置すると、通常は次のような名前になります。

C#
dataGridView1

この名前を使って、C#コードからDataGridViewを操作します。

たとえば、フォームが読み込まれたときに列を追加する場合は、Form_Loadイベントにコードを書きます。

C#
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
}

2-3. 列をデザイナーで追加する方法

DataGridViewの列は、Visual Studioのデザイナー画面から追加できます。

DataGridViewを選択し、右上の小さな三角マークをクリックします。そこから「列の編集」を選ぶと、列を追加できます。

列を追加するときは、主に次の項目を設定します。

C#
Name: Id
HeaderText: ID

NameはC#コードから列を指定するときに使う名前です。HeaderTextは画面に表示される列見出しです。

初心者のうちは、NameとHeaderTextの違いを意識しておくとエラーを減らせます。

2-4. 列をC#コードで追加する方法

列はC#コードでも追加できます。

C#
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
}

第1引数の"Id"は列名、 第2引数の"ID"はヘッダーに表示される文字です。

列名を使ってセルの値を取得する場合は、次のように書けます。

C#
string name = dataGridView1.Rows[0].Cells["Name"].Value.ToString();

コードで列を追加する方法は、動的に列を作りたい場合に便利です。

2-5. よく使う基本プロパティ一覧

DataGridViewでは、よく使うプロパティを覚えておくと便利です。

C#
dataGridView1.AllowUserToAddRows = false;
dataGridView1.ReadOnly = true;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

AllowUserToAddRowsは、最下行に自動で表示される新規入力行を表示するかどうかを設定します。

ReadOnlyは、セルを編集可能にするかどうかを設定します。

SelectionModeをFullRowSelectにすると、セルではなく行全体を選択できます。

MultiSelectをfalseにすると、複数行選択を禁止できます。

AutoSizeColumnsModeをFillにすると、列幅がDataGridView全体に合わせて自動調整されます。

3. DataGridViewにデータを表示する方法

3-1. セルに直接値を入れて表示する

一番シンプルな方法は、列と行を追加して、セルに直接値を入れる方法です。

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", "山田太郎", "25");
dataGridView1.Rows.Add("2", "佐藤花子", "30");
dataGridView1.Rows.Add("3", "鈴木一郎", "28");
}

この方法は、簡単なサンプルや固定データの表示に向いています。

ただし、データが多くなったり、検索やソートを本格的に行ったりする場合は、DataTableやBindingSourceを使う方が管理しやすくなります。

3-2. Rows.Addで複数行を追加する

Rows.Addを使うと、DataGridViewに行を追加できます。

C#
dataGridView1.Rows.Add("1", "山田太郎", "25");
dataGridView1.Rows.Add("2", "佐藤花子", "30");

列数と追加する値の数は基本的に合わせます。

たとえば列が3つある場合は、Rows.Addにも3つの値を指定します。

C#
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");

dataGridView1.Rows.Add("1", "山田太郎", "25");

列を作成していない状態でRows.Addを使うと、期待通りに表示されないことがあります。まず列を作ってから行を追加しましょう。

3-3. DataTableを使ってデータを表示する

DataTableを使うと、表形式のデータを管理しやすくなります。

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, "山田太郎", 25);
table.Rows.Add(2, "佐藤花子", 30);
table.Rows.Add(3, "鈴木一郎", 28);

dataGridView1.DataSource = table;
}

DataTableをDataSourceに設定すると、DataGridViewに自動で列と行が表示されます。

DataTableを使うメリットは、検索やソート、データベース連携がしやすくなることです。

3-4. Listやクラスのコレクションをバインドして表示する

クラスのListをDataGridViewに表示することもできます。

まず、表示したいデータ用のクラスを作ります。

C#
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}

次に、Listを作成してDataSourceに設定します。

C#
private void Form1_Load(object sender, EventArgs e)
{
List<Person> people = new List<Person>
{
new Person { Id = 1, Name = "山田太郎", Age = 25 },
new Person { Id = 2, Name = "佐藤花子", Age = 30 },
new Person { Id = 3, Name = "鈴木一郎", Age = 28 }
};

dataGridView1.DataSource = people;
}

この方法は、オブジェクト指向でデータを扱いたい場合に便利です。

ただし、Listをそのまま使う場合、後から追加・削除した内容が画面に自動反映されにくいことがあります。その場合はBindingListを使うと便利です。

C#
BindingList<Person> people = new BindingList<Person>();
dataGridView1.DataSource = people;

3-5. 表示されないときに確認するポイント

DataGridViewにデータが表示されない場合は、次の点を確認します。

まず、DataSourceに正しいデータを設定しているか確認します。

C#
dataGridView1.DataSource = table;

次に、列を手動で追加している場合、Rows.Addの前にColumns.Addを行っているか確認します。

C#
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Rows.Add("山田太郎");

また、AutoGenerateColumnsがfalseになっている場合、DataSourceを設定しても列が自動生成されません。

C#
dataGridView1.AutoGenerateColumns = true;

DataTableやListの中身が空の場合も、当然ながらデータは表示されません。デバッグで件数を確認しましょう。

C#
MessageBox.Show(table.Rows.Count.ToString());

4. DataGridViewの行・列・セルを操作する基本

4-1. 選択中の行を取得する

選択中の行を取得するには、SelectedRowsを使います。

C#
if (dataGridView1.SelectedRows.Count > 0)
{
DataGridViewRow row = dataGridView1.SelectedRows[0];
string name = row.Cells["Name"].Value.ToString();

MessageBox.Show(name);
}

SelectionModeをFullRowSelectにしておくと、行全体を選択しやすくなります。

C#
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

SelectedRowsを使う場合は、選択行が存在するかどうかを必ず確認しましょう。

4-2. 選択中のセルを取得する

選択中のセルを取得するには、CurrentCellを使います。

C#
if (dataGridView1.CurrentCell != null)
{
int rowIndex = dataGridView1.CurrentCell.RowIndex;
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;

object value = dataGridView1.Rows[rowIndex].Cells[columnIndex].Value;

MessageBox.Show(value?.ToString());
}

CurrentCellは、現在フォーカスがあるセルを表します。

選択中のセルの値だけを取得したい場合は、次のようにも書けます。

C#
string value = dataGridView1.CurrentCell.Value?.ToString();

4-3. セルの値を取得・変更する

セルの値を取得するには、RowsとCellsを使います。

C#
string name = dataGridView1.Rows[0].Cells[1].Value.ToString();

行番号と列番号は0から始まります。Rows[0]は1行目、Cells[1]は2列目です。

セルの値を変更するには、Valueに新しい値を代入します。

C#
dataGridView1.Rows[0].Cells[1].Value = "田中次郎";

列名を指定することもできます。

C#
dataGridView1.Rows[0].Cells["Name"].Value = "田中次郎";

列番号よりも列名を使った方が、列の順番が変わってもコードが壊れにくくなります。

4-4. 行番号や列名を指定して値を扱う

DataGridViewでは、行番号と列名を組み合わせてセルの値を扱えます。

C#
int rowIndex = 0;
string columnName = "Name";

string value = dataGridView1.Rows[rowIndex].Cells[columnName].Value?.ToString();

列名を使う場合は、Columns.Addの第1引数で指定したNameを使います。

C#
dataGridView1.Columns.Add("Name", "名前");

この場合、列名は"Name"です。"名前"ではありません。

初心者がよく間違えるポイントなので注意しましょう。

4-5. Nullや空文字でエラーを出さない書き方

セルの値がnullの場合、ToStringを直接呼ぶとNullReferenceExceptionが発生します。

エラーになりやすい書き方は次の通りです。

C#
string value = dataGridView1.Rows[0].Cells["Name"].Value.ToString();

安全に書くなら、null条件演算子を使います。

C#
string value = dataGridView1.Rows[0].Cells["Name"].Value?.ToString() ?? "";

または、Convert.ToStringを使う方法もあります。

C#
string value = Convert.ToString(dataGridView1.Rows[0].Cells["Name"].Value);

Convert.ToStringは、値がnullでも空文字として扱いやすいため、DataGridViewではよく使われます。

5. DataGridViewにデータを追加する方法

5-1. ボタンを押して新しい行を追加する

ボタンをクリックしたときにDataGridViewへ行を追加するには、ButtonのClickイベントにRows.Addを書きます。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Add("4", "田中次郎", "35");
}

ただし、Rows.Addを使うには、DataGridViewに列が作成されている必要があります。

C#
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");
}

この状態でボタンを押すと、新しい行が追加されます。

5-2. テキストボックスの入力値をDataGridViewに追加する

実際のアプリでは、TextBoxに入力した値をDataGridViewに追加することが多いです。

たとえば、txtId、txtName、txtAgeというTextBoxがある場合は、次のように書けます。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
string id = txtId.Text;
string name = txtName.Text;
string age = txtAge.Text;

dataGridView1.Rows.Add(id, name, age);
}

追加後にTextBoxをクリアする場合は、次のようにします。

C#
txtId.Clear();
txtName.Clear();
txtAge.Clear();
txtId.Focus();

全体では次のようになります。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Add(txtId.Text, txtName.Text, txtAge.Text);

txtId.Clear();
txtName.Clear();
txtAge.Clear();
txtId.Focus();
}

5-3. 入力チェックをしてから追加する

入力値が空のまま追加されると、後でエラーや不正データの原因になります。

追加前に入力チェックを行いましょう。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtId.Text))
{
MessageBox.Show("IDを入力してください。");
return;
}

if (string.IsNullOrWhiteSpace(txtName.Text))
{
MessageBox.Show("名前を入力してください。");
return;
}

if (!int.TryParse(txtAge.Text, out int age))
{
MessageBox.Show("年齢は数値で入力してください。");
return;
}

dataGridView1.Rows.Add(txtId.Text, txtName.Text, age);
}

int.TryParseを使うと、数値に変換できるかを安全にチェックできます。

5-4. DataTableに行を追加してDataGridViewへ反映する

DataTableをDataSourceにしている場合は、DataGridViewに直接Rows.Addするのではなく、DataTableに行を追加します。

C#
DataTable table = new DataTable();

private void Form1_Load(object sender, EventArgs e)
{
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));

table.Rows.Add(1, "山田太郎", 25);

dataGridView1.DataSource = table;
}

ボタンで追加する場合は、次のように書きます。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
table.Rows.Add(2, "佐藤花子", 30);
}

DataGridViewはDataTableにバインドされているため、DataTableに追加すると画面にも反映されます。

5-5. 追加できないときの原因と対処法

DataGridViewに行を追加できない場合、まずDataSourceが設定されているか確認しましょう。

DataSourceを使っている状態で、DataGridView.Rows.Addを呼ぶとエラーになることがあります。

C#
dataGridView1.DataSource = table;
dataGridView1.Rows.Add("1", "山田太郎", "25");

このような場合は、DataGridViewではなくDataTableに追加します。

C#
table.Rows.Add(1, "山田太郎", 25);

また、ReadOnlyがtrueになっていても、コードからの追加自体は可能ですが、ユーザーの直接入力はできません。

C#
dataGridView1.ReadOnly = false;

列が存在しない状態でRows.Addしていないか、列数と値の数が大きく違っていないかも確認しましょう。

6. DataGridViewのデータを削除する方法

6-1. 選択中の行を削除する

選択中の行を削除するには、SelectedRowsを使います。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0)
{
dataGridView1.Rows.Remove(dataGridView1.SelectedRows[0]);
}
}

選択行がない状態で削除しようとするとエラーになるため、SelectedRows.Countを確認します。

また、新規行を削除しようとするとエラーになることがあるため、IsNewRowも確認すると安全です。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("削除する行を選択してください。");
return;
}

DataGridViewRow row = dataGridView1.SelectedRows[0];

if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}

6-2. 複数選択した行を削除する

複数行を削除する場合は、SelectedRowsをforeachで処理します。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}
}

複数選択を許可するには、MultiSelectをtrueにします。

C#
dataGridView1.MultiSelect = true;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

複数行削除では、削除対象に新規行が含まれないようにIsNewRowを確認するのがポイントです。

6-3. 削除前に確認メッセージを表示する

誤って削除しないように、削除前に確認メッセージを表示すると親切です。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("削除する行を選択してください。");
return;
}

DialogResult result = MessageBox.Show(
"選択した行を削除しますか?",
"確認",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question
);

if (result == DialogResult.Yes)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}
}
}

業務アプリでは、削除処理の前に確認ダイアログを出すことがよくあります。

6-4. DataTableやBindingSourceから削除する

DataTableをDataSourceにしている場合は、DataGridViewの行を直接削除するより、BindingSourceやDataTable側から削除する方が管理しやすいです。

BindingSourceを使う例です。

C#
BindingSource bindingSource = new BindingSource();
DataTable table = new DataTable();

private void Form1_Load(object sender, EventArgs e)
{
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));

table.Rows.Add(1, "山田太郎");
table.Rows.Add(2, "佐藤花子");

bindingSource.DataSource = table;
dataGridView1.DataSource = bindingSource;
}

選択中の行を削除するには、次のようにします。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
if (bindingSource.Current != null)
{
bindingSource.RemoveCurrent();
}
}

BindingSourceを使うと、検索やソート、追加、削除の管理がしやすくなります。

6-5. 削除時によくあるエラーと回避方法

削除時によくあるエラーは、「選択行がない」「新規行を削除しようとしている」「DataSource使用中にRows.Removeを使っている」などです。

安全に削除するには、次のようにチェックします。

C#
if (dataGridView1.SelectedRows.Count == 0)
{
return;
}

DataGridViewRow row = dataGridView1.SelectedRows[0];

if (row.IsNewRow)
{
return;
}

dataGridView1.Rows.Remove(row);

DataSourceを使っている場合は、元データ側から削除します。

C#
bindingSource.RemoveCurrent();

また、foreachで削除するときにコレクションが変更される問題が気になる場合は、削除対象をListにコピーしてから削除すると安全です。

C#
List<DataGridViewRow> rows = new List<DataGridViewRow>();

foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
rows.Add(row);
}

foreach (DataGridViewRow row in rows)
{
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}

7. DataGridViewで検索する方法

7-1. 特定の文字列を含む行を検索する

DataGridView内のセルを順番に調べれば、特定の文字列を含む行を検索できます。

C#
private void SearchText(string keyword)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

string name = Convert.ToString(row.Cells["Name"].Value);

if (name.Contains(keyword))
{
row.Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
break;
}
}
}

Containsを使うと、部分一致で検索できます。

たとえば「山」と入力すると、「山田太郎」が見つかります。

7-2. TextBoxに入力したキーワードで検索する

TextBoxに入力したキーワードで検索するには、ボタンのClickイベントでTextBoxの値を取得します。

C#
private void buttonSearch_Click(object sender, EventArgs e)
{
string keyword = txtSearch.Text;

foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

string name = Convert.ToString(row.Cells["Name"].Value);

if (name.Contains(keyword))
{
row.Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
return;
}
}

MessageBox.Show("該当するデータがありません。");
}

検索前に現在の選択状態を解除したい場合は、ClearSelectionを使います。

C#
dataGridView1.ClearSelection();

7-3. 検索結果の行を選択・ハイライト表示する

検索結果を分かりやすくするには、該当行の背景色を変更します。

C#
private void buttonSearch_Click(object sender, EventArgs e)
{
string keyword = txtSearch.Text;

foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.DefaultCellStyle.BackColor = Color.White;
}

foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

string name = Convert.ToString(row.Cells["Name"].Value);

if (name.Contains(keyword))
{
row.DefaultCellStyle.BackColor = Color.Yellow;
row.Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
}
}
}

検索結果が複数ある場合は、該当するすべての行をハイライトできます。

検索結果を1件だけ選択したい場合は、見つかった時点でbreakまたはreturnを使います。

7-4. DataTableのRowFilterで絞り込み検索する

DataTableを使っている場合は、DataViewのRowFilterで絞り込み検索ができます。

C#
DataTable table = new DataTable();

private void Form1_Load(object sender, EventArgs e)
{
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));

table.Rows.Add(1, "山田太郎", 25);
table.Rows.Add(2, "佐藤花子", 30);
table.Rows.Add(3, "鈴木一郎", 28);

dataGridView1.DataSource = table;
}

検索ボタンでは次のようにRowFilterを設定します。

C#
private void buttonSearch_Click(object sender, EventArgs e)
{
string keyword = txtSearch.Text.Replace("'", "''");

DataView view = table.DefaultView;
view.RowFilter = $"Name LIKE '%{keyword}%'";
}

RowFilterを解除するには、空文字を設定します。

C#
table.DefaultView.RowFilter = "";

DataTableを使った絞り込み検索は、一覧画面で非常によく使われます。

7-5. 大文字小文字や部分一致検索の考え方

C#で文字列検索を行う場合、大文字小文字を区別するかどうかを考える必要があります。

単純なContainsでは、条件によって大文字小文字が区別されます。

C#
if (name.Contains(keyword))
{
// 一致
}

大文字小文字を区別したくない場合は、IndexOfを使います。

C#
if (name.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
{
// 一致
}

英数字を検索する場合は、この書き方が便利です。

C#
string name = Convert.ToString(row.Cells["Name"].Value);

if (name.IndexOf(txtSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0)
{
row.Selected = true;
}

日本語検索では大文字小文字の影響は少ないですが、英数字の商品コードやメールアドレスを検索する場合は意識しましょう。

8. DataGridViewでソートする方法

8-1. 列ヘッダークリックで並び替える

DataGridViewでは、列ヘッダーをクリックすると自動でソートできる場合があります。

DataTableやListなどをDataSourceに設定している場合、列ヘッダークリックで並び替えができることがあります。

列ごとのソート設定は、SortModeで指定できます。

C#
dataGridView1.Columns["Name"].SortMode = DataGridViewColumnSortMode.Automatic;

ユーザーに列ヘッダークリックでソートさせたい場合は、Automaticを指定します。

C#
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.SortMode = DataGridViewColumnSortMode.Automatic;
}

8-2. C#コードで昇順・降順ソートする

コードからDataGridViewをソートするには、Sortメソッドを使います。

C#
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Ascending);

降順にする場合は、Descendingを指定します。

C#
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Descending);

ListSortDirectionを使うために、次の名前空間を追加します。

C#
using System.ComponentModel;

ボタンでソートする場合は、次のように書けます。

C#
private void buttonSort_Click(object sender, EventArgs e)
{
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Ascending);
}

8-3. 数値・日付・文字列のソートで注意すること

DataGridViewのソートでは、データ型が重要です。

たとえば、数値を文字列として扱うと、次のような順番になることがあります。

C#
1
10
2

これは文字列として比較されているためです。数値として正しくソートしたい場合は、DataTableの列型をintにします。

C#
table.Columns.Add("Age", typeof(int));

日付も同じです。文字列ではなくDateTime型にすると、正しく日付順でソートできます。

C#
table.Columns.Add("Birthday", typeof(DateTime));

データ型を正しく設定することで、ソート結果が期待通りになります。

8-4. DataTableやBindingSourceを使ったソート

DataTableを使っている場合は、DefaultView.Sortを使ってソートできます。

C#
table.DefaultView.Sort = "Age ASC";

降順にする場合はDESCを使います。

C#
table.DefaultView.Sort = "Age DESC";

BindingSourceを使っている場合は、Sortプロパティを使います。

C#
bindingSource.Sort = "Name ASC";

複数列でソートすることもできます。

C#
bindingSource.Sort = "Age ASC, Name ASC";

一覧画面で検索とソートを組み合わせる場合は、DataTableとBindingSourceを使うと管理しやすくなります。

8-5. ソートできないときの原因と対処法

ソートできない場合は、まず列のSortModeを確認します。

C#
dataGridView1.Columns["Name"].SortMode = DataGridViewColumnSortMode.Automatic;

次に、DataSourceに設定しているデータがソートに対応しているか確認します。

DataTableやBindingSourceはソートしやすいですが、単純なListは列ヘッダークリックで期待通りにソートできないことがあります。

その場合は、BindingListやBindingSourceを使うか、LINQで並び替えて再設定します。

C#
people = people.OrderBy(p => p.Age).ToList();
dataGridView1.DataSource = null;
dataGridView1.DataSource = people;

また、数値や日付が文字列として入っていると、見た目と違う順番になることがあります。列の型も確認しましょう。

9. DataGridViewの見た目を整える方法

9-1. 列幅を自動調整する

列幅を自動調整するには、AutoSizeColumnsModeを使います。

C#
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

Fillを指定すると、DataGridViewの幅に合わせて列幅が自動調整されます。

すべてのセル内容に合わせたい場合は、AllCellsを使います。

C#
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

特定の列だけ幅を指定することもできます。

C#
dataGridView1.Columns["Name"].Width = 150;

画面レイアウトに合わせて使い分けましょう。

9-2. ヘッダー名を変更する

列ヘッダーに表示される名前は、HeaderTextで変更できます。

C#
dataGridView1.Columns["Id"].HeaderText = "ID";
dataGridView1.Columns["Name"].HeaderText = "氏名";
dataGridView1.Columns["Age"].HeaderText = "年齢";

DataTableやクラスのプロパティ名をそのまま表示すると、英語の列名になることがあります。

その場合は、HeaderTextを使って日本語の見出しに変更すると見やすくなります。

9-3. セルの文字寄せを変更する

セルの文字寄せは、DefaultCellStyle.Alignmentで変更できます。

C#
dataGridView1.Columns["Age"].DefaultCellStyle.Alignment =
DataGridViewContentAlignment.MiddleRight;

数値は右寄せ、文字列は左寄せにすると見やすくなります。

ヘッダーの文字寄せを変更する場合は、HeaderCell.Style.Alignmentを使います。

C#
dataGridView1.Columns["Age"].HeaderCell.Style.Alignment =
DataGridViewContentAlignment.MiddleCenter;

全体のセルを中央寄せにすることもできます。

C#
dataGridView1.DefaultCellStyle.Alignment =
DataGridViewContentAlignment.MiddleCenter;

9-4. 行の背景色を変更する

行の背景色はDefaultCellStyle.BackColorで変更できます。

C#
dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightYellow;

交互に背景色を変えると、一覧が見やすくなります。

C#
dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray;

特定の条件に応じて色を変えることもできます。

C#
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

int age = Convert.ToInt32(row.Cells["Age"].Value);

if (age >= 30)
{
row.DefaultCellStyle.BackColor = Color.LightBlue;
}
}

業務アプリでは、期限切れ、警告、完了済みなどの状態を色で表すと分かりやすくなります。

9-5. 読み取り専用にする

DataGridViewを読み取り専用にするには、ReadOnlyをtrueにします。

C#
dataGridView1.ReadOnly = true;

特定の列だけ読み取り専用にすることもできます。

C#
dataGridView1.Columns["Id"].ReadOnly = true;

たとえば、ID列は編集不可、名前や年齢は編集可にしたい場合に使います。

C#
dataGridView1.Columns["Id"].ReadOnly = true;
dataGridView1.Columns["Name"].ReadOnly = false;
dataGridView1.Columns["Age"].ReadOnly = false;

9-6. チェックボックス列・ボタン列を追加する

チェックボックス列を追加するには、DataGridViewCheckBoxColumnを使います。

C#
DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "Select";
checkColumn.HeaderText = "選択";

dataGridView1.Columns.Add(checkColumn);

ボタン列を追加するには、DataGridViewButtonColumnを使います。

C#
DataGridViewButtonColumn buttonColumn = new DataGridViewButtonColumn();
buttonColumn.Name = "DeleteButton";
buttonColumn.HeaderText = "操作";
buttonColumn.Text = "削除";
buttonColumn.UseColumnTextForButtonValue = true;

dataGridView1.Columns.Add(buttonColumn);

ボタン列を使うと、各行に「編集」「削除」「詳細」などのボタンを表示できます。

10. DataGridViewの編集・入力を制御する方法

10-1. セル編集を許可・禁止する

セル編集を許可するには、ReadOnlyをfalseにします。

C#
dataGridView1.ReadOnly = false;

編集を禁止するにはtrueにします。

C#
dataGridView1.ReadOnly = true;

特定の列だけ編集禁止にする場合は、列のReadOnlyを設定します。

C#
dataGridView1.Columns["Id"].ReadOnly = true;

IDや登録日時など、ユーザーに変更されたくない項目は読み取り専用にしておきましょう。

10-2. 新規行の自動追加を無効にする

DataGridViewでは、初期状態で一番下に新規入力用の空行が表示されることがあります。

これを非表示にするには、AllowUserToAddRowsをfalseにします。

C#
dataGridView1.AllowUserToAddRows = false;

一覧表示だけを目的とする場合は、falseにしておくと見た目がすっきりします。

ユーザーに直接行追加させたい場合はtrueのままでも構いません。

C#
dataGridView1.AllowUserToAddRows = true;

10-3. 入力値を検証する

セルに入力された値を検証するには、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にすると、入力が確定されません。

入力チェックは、データの不整合を防ぐために重要です。

10-4. セル編集後のイベントを使う

セルの編集が終わった後に処理を行うには、CellEndEditやCellValueChangedを使います。

C#
private void dataGridView1_CellEndEdit(
object sender,
DataGridViewCellEventArgs e)
{
string value = Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
MessageBox.Show("編集後の値: " + value);
}

CellValueChangedは、セルの値が変更されたときに発生します。

C#
private void dataGridView1_CellValueChanged(
object sender,
DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
Console.WriteLine("セルの値が変更されました。");
}
}

編集後に合計金額を再計算したり、変更フラグを立てたりする場合に便利です。

10-5. コンボボックス列を使って入力候補を表示する

DataGridViewにコンボボックス列を追加すると、ユーザーに選択肢から値を選ばせることができます。

C#
DataGridViewComboBoxColumn comboColumn = new DataGridViewComboBoxColumn();
comboColumn.Name = "Category";
comboColumn.HeaderText = "カテゴリ";
comboColumn.Items.Add("食品");
comboColumn.Items.Add("家電");
comboColumn.Items.Add("日用品");

dataGridView1.Columns.Add(comboColumn);

カテゴリやステータスなど、入力値を限定したい項目に向いています。

たとえば、ステータス列なら次のようにできます。

C#
comboColumn.Items.Add("未対応");
comboColumn.Items.Add("対応中");
comboColumn.Items.Add("完了");

入力ミスを減らしたい場合は、TextBox入力よりもコンボボックス列が便利です。

11. DataGridViewでよく使うイベント

11-1. CellClickでセルクリックを検知する

CellClickイベントを使うと、セルがクリックされたときの処理を書けます。

C#
private void dataGridView1_CellClick(
object sender,
DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;

string name = Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells["Name"].Value);
MessageBox.Show(name);
}

e.RowIndexが-1の場合はヘッダーがクリックされています。セルの行を処理する場合は、e.RowIndex >= 0を確認しましょう。

C#
if (e.RowIndex < 0)
{
return;
}

11-2. CellContentClickでボタン列やチェックボックス列を扱う

ボタン列やチェックボックス列をクリックしたときは、CellContentClickを使うことが多いです。

C#
private void dataGridView1_CellContentClick(
object sender,
DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;

if (dataGridView1.Columns[e.ColumnIndex].Name == "DeleteButton")
{
dataGridView1.Rows.RemoveAt(e.RowIndex);
}
}

ボタン列のNameを確認して処理を分けるのがポイントです。

チェックボックス列の場合も、列名を見て処理できます。

C#
if (dataGridView1.Columns[e.ColumnIndex].Name == "Select")
{
bool isChecked = Convert.ToBoolean(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
}

11-3. CellValueChangedで値の変更を検知する

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

これにより、チェックボックスをクリックしたタイミングでCellValueChangedを発生させやすくなります。

11-4. SelectionChangedで選択行の変更を検知する

SelectionChangedイベントは、選択行や選択セルが変わったときに発生します。

C#
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0) return;

DataGridViewRow row = dataGridView1.SelectedRows[0];

txtId.Text = Convert.ToString(row.Cells["Id"].Value);
txtName.Text = Convert.ToString(row.Cells["Name"].Value);
txtAge.Text = Convert.ToString(row.Cells["Age"].Value);
}

選択した行の内容をTextBoxに表示したい場合によく使います。

一覧から選択して、詳細欄に値を表示する画面では定番のイベントです。

11-5. DataErrorで入力エラーを処理する

DataGridViewでデータ型が合わない値を入力すると、エラーが発生することがあります。

DataErrorイベントを使うと、エラー時の処理を書けます。

C#
private void dataGridView1_DataError(
object sender,
DataGridViewDataErrorEventArgs e)
{
MessageBox.Show("入力値が正しくありません。");
e.ThrowException = false;
}

特に、コンボボックス列やDataTableの型が決まっている列ではDataErrorが発生しやすいです。

アプリが突然止まらないように、DataErrorイベントでエラーを処理しておくと安心です。

12. DataGridViewとデータベースを連携する基本

12-1. データベースのデータをDataGridViewに表示する流れ

DataGridViewは、SQL Server、Access、SQLiteなどのデータベースと連携して使うことができます。

基本的な流れは次の通りです。

まず、データベースへ接続します。次に、SQLを実行してデータを取得します。取得したデータをDataTableに入れます。最後に、DataGridViewのDataSourceにDataTableを設定します。

C#
dataGridView1.DataSource = table;

DataGridViewに直接データベースを設定するのではなく、DataTableなどを経由して表示するのが一般的です。

12-2. SQL Serverのデータを表示するサンプル

SQL ServerのデータをDataGridViewに表示するサンプルです。

C#
using System.Data;
using System.Data.SqlClient;
C#
private void LoadData()
{
string connectionString =
"Data Source=localhost;Initial Catalog=SampleDb;Integrated Security=True";

string sql = "SELECT Id, Name, Age FROM People";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, connection))
{
DataTable table = new DataTable();
adapter.Fill(table);

dataGridView1.DataSource = table;
}
}

フォーム読み込み時に呼び出す場合は、次のようにします。

C#
private void Form1_Load(object sender, EventArgs e)
{
LoadData();
}

接続文字列は環境によって変わるため、自分のSQL Server名やデータベース名に合わせて変更してください。

12-3. AccessやSQLiteと連携する場合の考え方

AccessやSQLiteでも、基本的な考え方はSQL Serverと同じです。

データベースへ接続し、SQLでデータを取得し、DataTableに入れて、DataGridViewに表示します。

SQLiteの場合は、SQLite用のライブラリを使って接続します。

C#
// SQLiteでも流れは同じ
// 1. 接続する
// 2. SELECT文を実行する
// 3. DataTableに入れる
// 4. DataGridView.DataSourceに設定する

Accessの場合は、OleDbConnectionを使うことが多いです。

C#
using System.Data.OleDb;

どのデータベースでも、DataGridView側の扱いは大きく変わりません。違うのは接続方法と接続文字列です。

12-4. 追加・更新・削除をデータベースへ反映する

DataGridView上で変更した内容をデータベースへ反映するには、INSERT、UPDATE、DELETE文を実行します。

たとえば、追加の場合はINSERT文を使います。

C#
string sql = "INSERT INTO People (Name, Age) VALUES (@Name, @Age)";

更新の場合はUPDATE文です。

C#
string sql = "UPDATE People SET Name = @Name, Age = @Age WHERE Id = @Id";

削除の場合はDELETE文です。

C#
string sql = "DELETE FROM People WHERE Id = @Id";

実際のアプリでは、DataGridViewで選択された行からIDを取得し、そのIDを条件にして更新・削除することが多いです。

C#
int id = Convert.ToInt32(dataGridView1.SelectedRows[0].Cells["Id"].Value);

SQLを文字列連結で作るとSQLインジェクションの危険があるため、パラメータを使いましょう。

12-5. データベース連携で初心者がつまずきやすいポイント

データベース連携で初心者がつまずきやすいのは、接続文字列、テーブル名、列名、データ型、更新タイミングです。

接続文字列が間違っていると、そもそもデータベースに接続できません。

SQLの列名とDataGridViewの列名が違うと、値の取得でエラーになります。

C#
row.Cells["Name"].Value

この"Name"が実際に存在する列名か確認しましょう。

また、DataGridViewに表示されているデータを編集しただけでは、必ずしもデータベースに保存されるわけではありません。保存ボタンを用意し、UPDATE文などを実行する必要があります。

13. DataGridViewでよくあるエラーと解決方法

13-1. インデックスが範囲外です

「インデックスが範囲外です」というエラーは、存在しない行番号や列番号を指定したときに発生します。

たとえば、行が1件もないのにRows[0]を指定するとエラーになります。

C#
string name = dataGridView1.Rows[0].Cells[0].Value.ToString();

安全に書くには、行数を確認します。

C#
if (dataGridView1.Rows.Count > 0)
{
string name = Convert.ToString(dataGridView1.Rows[0].Cells[0].Value);
}

選択行の場合も、SelectedRows.Countを確認しましょう。

C#
if (dataGridView1.SelectedRows.Count > 0)
{
DataGridViewRow row = dataGridView1.SelectedRows[0];
}

13-2. NullReferenceExceptionが発生する

NullReferenceExceptionは、nullの値に対してToStringなどを呼び出したときに発生します。

DataGridViewのセルが空の場合、Valueがnullになることがあります。

危険な書き方です。

C#
string value = dataGridView1.Rows[0].Cells["Name"].Value.ToString();

安全な書き方です。

C#
string value = Convert.ToString(dataGridView1.Rows[0].Cells["Name"].Value);

または、null条件演算子を使います。

C#
string value = dataGridView1.Rows[0].Cells["Name"].Value?.ToString() ?? "";

DataGridViewでは空セルを扱うことが多いため、null対策は必ず行いましょう。

13-3. 列名が見つからない

列名が見つからないエラーは、Cells["Name"]のように指定した列名が存在しない場合に発生します。

C#
row.Cells["Name"].Value

この"Name"は、画面に表示されているヘッダー名ではなく、列のNameです。

たとえば、次のように列を追加した場合です。

C#
dataGridView1.Columns.Add("Name", "名前");

列名は"Name"で、ヘッダー表示は"名前"です。

DataTableをDataSourceにしている場合は、DataTableの列名を確認しましょう。

C#
table.Columns.Add("Name", typeof(string));

列名のスペルミスや大文字小文字の違いにも注意が必要です。

13-4. データが更新されない

DataGridViewの画面上で値を変更しても、元データやデータベースに反映されないことがあります。

DataTableを使っている場合は、編集内容がDataTableに反映されているか確認します。

C#
dataGridView1.EndEdit();

BindingSourceを使っている場合は、EndEditを呼び出します。

C#
bindingSource.EndEdit();

データベースへ保存する場合は、UPDATE文やDataAdapterのUpdate処理が必要です。

画面の表示を更新したいだけなら、DataSourceを再設定する方法もあります。

C#
dataGridView1.DataSource = null;
dataGridView1.DataSource = table;

ただし、再設定すると選択状態などがリセットされるため注意しましょう。

13-5. ソートや検索が期待通りに動かない

ソートが期待通りに動かない場合は、データ型を確認します。

数値が文字列として入っていると、1、10、2のような順番になることがあります。

C#
table.Columns.Add("Age", typeof(int));

検索が期待通りに動かない場合は、対象列、検索条件、空白、大文字小文字を確認します。

C#
string keyword = txtSearch.Text.Trim();

RowFilterを使う場合は、シングルクォートをエスケープします。

C#
string keyword = txtSearch.Text.Replace("'", "''");
table.DefaultView.RowFilter = $"Name LIKE '%{keyword}%'";

検索前に空文字かどうかを確認することも大切です。

C#
if (string.IsNullOrWhiteSpace(keyword))
{
table.DefaultView.RowFilter = "";
return;
}

13-6. 行削除時に例外が発生する

行削除時の例外は、新規行を削除しようとした場合や、DataSource使用中に直接Rows.Removeした場合に起こりやすいです。

新規行を除外するには、IsNewRowを確認します。

C#
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}

DataSourceを使っている場合は、元データ側から削除します。

C#
bindingSource.RemoveCurrent();

また、選択行がない状態で削除しないようにします。

C#
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("削除する行を選択してください。");
return;
}

削除処理では、選択チェック、新規行チェック、DataSourceの有無を確認することが重要です。

14. 初心者向けDataGridViewサンプルコード集

14-1. 基本表示のサンプルコード

DataGridViewに基本的なデータを表示するサンプルです。

C#
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.AllowUserToAddRows = false;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");

dataGridView1.Rows.Add("1", "山田太郎", "25");
dataGridView1.Rows.Add("2", "佐藤花子", "30");
dataGridView1.Rows.Add("3", "鈴木一郎", "28");
}

まずはこのコードで、DataGridViewに列と行を表示する基本を理解しましょう。

14-2. 追加処理のサンプルコード

TextBoxの入力値をDataGridViewに追加するサンプルです。

C#
private void buttonAdd_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtId.Text))
{
MessageBox.Show("IDを入力してください。");
return;
}

if (string.IsNullOrWhiteSpace(txtName.Text))
{
MessageBox.Show("名前を入力してください。");
return;
}

if (!int.TryParse(txtAge.Text, out int age))
{
MessageBox.Show("年齢は数値で入力してください。");
return;
}

dataGridView1.Rows.Add(txtId.Text, txtName.Text, age);

txtId.Clear();
txtName.Clear();
txtAge.Clear();
}

入力チェックを入れることで、不正なデータの追加を防げます。

14-3. 削除処理のサンプルコード

選択行を削除するサンプルです。

C#
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("削除する行を選択してください。");
return;
}

DialogResult result = MessageBox.Show(
"選択した行を削除しますか?",
"確認",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question
);

if (result != DialogResult.Yes)
{
return;
}

foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (!row.IsNewRow)
{
dataGridView1.Rows.Remove(row);
}
}
}

削除前の確認メッセージを入れると、誤操作を防げます。

14-4. 検索処理のサンプルコード

TextBoxのキーワードで検索し、該当行をハイライトするサンプルです。

C#
private void buttonSearch_Click(object sender, EventArgs e)
{
string keyword = txtSearch.Text.Trim();

dataGridView1.ClearSelection();

foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.DefaultCellStyle.BackColor = Color.White;
}

if (string.IsNullOrWhiteSpace(keyword))
{
return;
}

bool found = false;

foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

string name = Convert.ToString(row.Cells["Name"].Value);

if (name.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
{
row.Selected = true;
row.DefaultCellStyle.BackColor = Color.Yellow;
dataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
found = true;
}
}

if (!found)
{
MessageBox.Show("該当するデータがありません。");
}
}

部分一致検索を行い、検索結果を視覚的に分かりやすく表示できます。

14-5. ソート処理のサンプルコード

名前列で昇順ソートするサンプルです。

C#
using System.ComponentModel;
C#
private void buttonSortAsc_Click(object sender, EventArgs e)
{
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Ascending);
}

降順ソートする場合は次のようにします。

C#
private void buttonSortDesc_Click(object sender, EventArgs e)
{
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Descending);
}

DataTableを使っている場合は、DefaultView.Sortでもソートできます。

C#
table.DefaultView.Sort = "Age ASC";

14-6. 見た目を整えるサンプルコード

DataGridViewの見た目を整える基本コードです。

C#
private void SetGridStyle()
{
dataGridView1.AllowUserToAddRows = false;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray;

dataGridView1.Columns["Id"].HeaderText = "ID";
dataGridView1.Columns["Name"].HeaderText = "氏名";
dataGridView1.Columns["Age"].HeaderText = "年齢";

dataGridView1.Columns["Age"].DefaultCellStyle.Alignment =
DataGridViewContentAlignment.MiddleRight;
}

フォーム読み込み後やDataSource設定後に呼び出すと、見やすい一覧画面になります。

C#
private void Form1_Load(object sender, EventArgs e)
{
LoadData();
SetGridStyle();
}

15. C# DataGridViewの使い方でよくある質問

15-1. DataGridViewにデータが表示されない原因は?

DataGridViewにデータが表示されない原因として多いのは、DataSourceが設定されていない、列が作成されていない、データ自体が空、AutoGenerateColumnsがfalseになっている、列名が一致していない、などです。

まずは次の点を確認しましょう。

C#
dataGridView1.DataSource = table;

DataTableの行数も確認します。

C#
MessageBox.Show(table.Rows.Count.ToString());

コードで列と行を追加している場合は、Columns.Addの後にRows.Addしているか確認してください。

C#
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Rows.Add("山田太郎");

15-2. 選択行の値を取得するには?

選択行の値を取得するには、SelectedRowsを使います。

C#
if (dataGridView1.SelectedRows.Count > 0)
{
DataGridViewRow row = dataGridView1.SelectedRows[0];

string id = Convert.ToString(row.Cells["Id"].Value);
string name = Convert.ToString(row.Cells["Name"].Value);
string age = Convert.ToString(row.Cells["Age"].Value);

MessageBox.Show($"{id} {name} {age}");
}

SelectionModeをFullRowSelectにしておくと、行単位で選択しやすくなります。

C#
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

15-3. DataGridViewの内容をクリアするには?

DataGridViewの内容をクリアする方法は、使い方によって変わります。

Rows.Addで直接追加している場合は、Rows.Clearを使います。

C#
dataGridView1.Rows.Clear();

列も含めてクリアしたい場合は、Columns.Clearを使います。

C#
dataGridView1.Columns.Clear();

DataSourceを使っている場合は、DataSourceをnullにします。

C#
dataGridView1.DataSource = null;

DataTableの中身だけを消したい場合は、Clearを使います。

C#
table.Clear();

15-4. DataGridViewを読み取り専用にするには?

DataGridView全体を読み取り専用にするには、ReadOnlyをtrueにします。

C#
dataGridView1.ReadOnly = true;

特定の列だけ読み取り専用にすることもできます。

C#
dataGridView1.Columns["Id"].ReadOnly = true;

ユーザーに編集させたくない一覧画面では、ReadOnlyをtrueにしておくと安全です。

さらに新規行の追加も禁止したい場合は、次の設定をします。

C#
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;

15-5. DataGridViewのデータをCSV出力するには?

DataGridViewの内容をCSV出力するには、行と列を順番に読み取ってファイルに書き込みます。

C#
private void ExportCsv(string filePath)
{
using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
writer.Write(dataGridView1.Columns[i].HeaderText);

if (i < dataGridView1.Columns.Count - 1)
{
writer.Write(",");
}
}

writer.WriteLine();

foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.IsNewRow) continue;

for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
string value = Convert.ToString(row.Cells[i].Value);
value = value.Replace("\"", "\"\"");

writer.Write($"\"{value}\"");

if (i < dataGridView1.Columns.Count - 1)
{
writer.Write(",");
}
}

writer.WriteLine();
}
}
}

使用するには、次のように呼び出します。

C#
ExportCsv(@"C:\temp\data.csv");

CSVではカンマやダブルクォーテーションを含む値に注意が必要です。値をダブルクォーテーションで囲み、内部のダブルクォーテーションをエスケープすると安全です。

15-6. DataGridViewとDataTableはどちらを使うべき?

DataGridViewは画面に表を表示するためのコントロールで、DataTableは表形式のデータを管理するためのクラスです。

そのため、どちらか一方を選ぶというより、組み合わせて使うことが多いです。

簡単なサンプルや固定データなら、DataGridViewに直接Rows.Addしても問題ありません。

C#
dataGridView1.Rows.Add("1", "山田太郎", "25");

一方、検索、ソート、データベース連携、追加、削除、更新をしっかり管理したい場合は、DataTableを使う方がおすすめです。

C#
dataGridView1.DataSource = table;

初心者はまずRows.Addで基本を理解し、その後DataTableやBindingSourceを使う流れで学ぶと理解しやすいです。

まとめ

C#のDataGridViewは、Windowsフォームアプリケーションで表形式のデータを表示・編集するための便利なコントロールです。

基本的な使い方は、列を作成し、Rows.Addで行を追加することから始められます。より実践的なアプリでは、DataTableやBindingSourceを使ってDataGridViewにデータをバインドすると、検索、ソート、追加、削除、データベース連携が扱いやすくなります。

DataGridViewを使うときは、選択行の取得、セルの値の取得、null対策、列名の指定、DataSource使用時の追加・削除方法に注意しましょう。

特に初心者がつまずきやすいポイントは、DataSourceを使っているのにRows.AddやRows.Removeを直接使ってしまうこと、列名とヘッダー名を混同すること、セルのValueがnullのままToStringしてしまうことです。

まずは、次のような基本コードを理解することが大切です。

C#
dataGridView1.Columns.Add("Id", "ID");
dataGridView1.Columns.Add("Name", "名前");
dataGridView1.Columns.Add("Age", "年齢");

dataGridView1.Rows.Add("1", "山田太郎", "25");
dataGridView1.Rows.Add("2", "佐藤花子", "30");

その後、DataTableを使った表示に進むと、実務に近いDataGridViewの使い方を身につけられます。

C#
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, "山田太郎", 25);

dataGridView1.DataSource = table;

C# DataGridViewは、表示、追加、削除、検索、ソート、編集、データベース連携まで幅広く使える重要なコントロールです。この記事のサンプルを少しずつ試しながら、一覧画面を作る基本を身につけていきましょう。