DataGridView で行を追加する方法(サンプルあり)

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

DataGridView への行追加は、DataSource にバインドしているかどうかで方法が変わります。

バインドなしの場合は dataGridView1.Rows.Add() で直接追加できますが、バインドしている場合に同じコードを書くと実行時エラーになります。本記事では、状況別の行追加方法と、よくあるエラーの原因・対処法を C# サンプルコードとともに解説します。

バインドなし:Rows.Add() で直接追加

DataSource を設定せず、列を手動で追加している場合は Rows.Add() で直接行を追加できます。

// 値を直接指定して追加(列の順番に対応)
dataGridView1.Rows.Add("値1", "値2", "値3");

列数が多い場合や、追加後にセル値を個別に設定したい場合は、行オブジェクトを先に作ってから追加する方法が読みやすいです。

// 行オブジェクトを作ってから追加する
DataGridViewRow row = (DataGridViewRow)dataGridView1.Rows[0].Clone();
row.Cells[0].Value = "値1";
row.Cells[1].Value = "値2";
row.Cells[2].Value = "値3";
dataGridView1.Rows.Add(row);

注意: DataSource にデータをバインドしている状態で Rows.Add() を呼ぶと InvalidOperationException が発生します。バインドあり・なしの判断を最初に確認してください。

バインドあり(DataTable):DataTable に行を追加する

DataGridView に DataTable をバインドしている場合、行の追加は DataTable 側に対して行います。DataTable に行を追加すると、DataGridView の表示に自動的に反映されます。

// DataTable に新しい行を追加する(パターン①:値を直接指定)
DataRow newRow = _dataTable.NewRow();
newRow["ID"] = 4;
newRow["Name"] = "たろう";
newRow["Age"] = 30;
_dataTable.Rows.Add(newRow);

列の順番が決まっていて簡潔に書きたい場合は、値を直接渡す書き方も使えます。

// DataTable に新しい行を追加する(パターン②:列順に値を指定)
_dataTable.Rows.Add(4, "たろう", 30);

ポイント: _dataTable はフィールド変数として保持しておく必要があります。Form_Load 内でローカル変数に DataTable を作って DataSource に設定するだけでは、後から行を追加できません。

バインドあり(BindingList):BindingList に行を追加する

BindingList<T> をバインドしている場合は、リストにオブジェクトを追加するだけで DataGridView に反映されます。

// BindingList にオブジェクトを追加する
_products.Add(new Product { ID = 4, Name = "ぶどう", Price = 500 });

BindingList<T> は変更通知を持っているため、Add() を呼ぶだけで自動的に画面が更新されます。DataTable と違い、型安全に扱えるのが利点です。

よくあるエラーと原因

エラー①:InvalidOperationException(バインド中に Rows.Add を呼ぶ)

Terminal window
System.InvalidOperationException:
'DataSource が設定されている場合、行をプログラムで DataGridView に追加することはできません。'

原因: DataSource にバインドした状態で dataGridView1.Rows.Add() を呼んでいます。
対処: DataTable や BindingList など、バインドしているデータソース側に行を追加してください。

エラー②:行を追加したのに画面に反映されない

原因: DataTable をローカル変数で作成してバインドしたため、後からアクセスできていません。

// NG:Form_Load 内のローカル変数に DataTable を作成している
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable(); // ← ローカル変数
dt.Columns.Add("Name", typeof(string));
dataGridView1.DataSource = dt;
}
private void btnAdd_Click(object sender, EventArgs e)
{
// dt にアクセスできないため、行を追加できない
}

対処: DataTable をフィールド変数として宣言して保持してください。

// OK:フィールド変数として保持する
private DataTable _dataTable = new DataTable();
private void Form1_Load(object sender, EventArgs e)
{
_dataTable.Columns.Add("Name", typeof(string));
dataGridView1.DataSource = _dataTable;
}
private void btnAdd_Click(object sender, EventArgs e)
{
_dataTable.Rows.Add("たろう"); // フィールド変数なのでアクセス可能
}

エラー③:追加した行が最下行の「*」行の後に入らない

原因: AllowUserToAddRows = true(デフォルト)の状態では、「*」の新規追加行が常に最下行に表示されます。これは仕様通りの動作です。
対処: プログラムから行を追加する用途で新規追加行が不要な場合は、AllowUserToAddRows = false を設定してください。

dataGridView1.AllowUserToAddRows = false;

新規追加行の詳細な制御については、「DataGridView:新規追加行の表示・非表示制御と注意点」を参照してください。

ソースコード

サンプルコード

3つの行追加パターンをタブ切り替えで確認できるサンプルアプリです。「バインドなし」「DataTable バインド」「BindingList バインド」それぞれのボタンで行を追加し、動作の違いを確認できます。

Form1.cs
using System.ComponentModel;
namespace DataGridView_AddRow
{
public partial class Form1 : Form
{
// ── フィールド変数 ──────────────────────────────
// DataTable バインド用
private DataTable _dataTable = new DataTable();
// BindingList バインド用
private BindingList<Product> _products = new BindingList<Product>();
// ── コンストラクタ ──────────────────────────────
public Form1()
{
InitializeComponent();
// タブ①:バインドなし
SetupNoBindTab();
// タブ②:DataTable バインド
SetupDataTableTab();
// タブ③:BindingList バインド
SetupBindingListTab();
}
// ════════════════════════════════════════════════
// タブ①:バインドなし(Rows.Add で直接追加)
// ════════════════════════════════════════════════
private void SetupNoBindTab()
{
// 列を手動で追加
dataGridViewNoBind.Columns.Add("ColID", "ID");
dataGridViewNoBind.Columns.Add("ColName", "名前");
dataGridViewNoBind.Columns.Add("ColAge", "年齢");
dataGridViewNoBind.AllowUserToAddRows = false;
// ボタンクリックで行を追加
btnAddNoBind.Click += (s, e) =>
{
int nextId = dataGridViewNoBind.Rows.Count + 1;
dataGridViewNoBind.Rows.Add(nextId, $"ユーザー{nextId}", 20 + nextId);
};
}
// ════════════════════════════════════════════════
// タブ②:DataTable バインド
// ════════════════════════════════════════════════
private void SetupDataTableTab()
{
// DataTable の列定義
_dataTable.Columns.Add("ID", typeof(int));
_dataTable.Columns.Add("Name", typeof(string));
_dataTable.Columns.Add("Age", typeof(int));
// 初期データ
_dataTable.Rows.Add(1, "じゅんや", 23);
_dataTable.Rows.Add(2, "きょうこ", 25);
_dataTable.Rows.Add(3, "えみ", 24);
// DataGridView にバインド
dataGridViewDT.DataSource = _dataTable;
dataGridViewDT.AllowUserToAddRows = false;
// ボタンクリックで DataTable に行追加 → DataGridView に自動反映
btnAddDT.Click += (s, e) =>
{
int nextId = _dataTable.Rows.Count + 1;
DataRow newRow = _dataTable.NewRow();
newRow["ID"] = nextId;
newRow["Name"] = $"ユーザー{nextId}";
newRow["Age"] = 20 + nextId;
_dataTable.Rows.Add(newRow);
};
}
// ════════════════════════════════════════════════
// タブ③:BindingList バインド
// ════════════════════════════════════════════════
private void SetupBindingListTab()
{
// 初期データ
_products.Add(new Product { ID = 1, Name = "リンゴ", Price = 150 });
_products.Add(new Product { ID = 2, Name = "バナナ", Price = 100 });
_products.Add(new Product { ID = 3, Name = "メロン", Price = 800 });
// DataGridView にバインド
dataGridViewBL.DataSource = _products;
dataGridViewBL.AllowUserToAddRows = false;
// ボタンクリックで BindingList にオブジェクト追加 → 自動反映
btnAddBL.Click += (s, e) =>
{
int nextId = _products.Count + 1;
_products.Add(new Product
{
ID = nextId,
Name = $"商品{nextId}",
Price = nextId * 100
});
};
}
}
// ── BindingList 用データクラス ──────────────────────
public class Product
{
public int ID { get; set; }
public string Name { get; set; } = string.Empty;
public int Price { get; set; }
// 【ポイント】引数付きコンストラクタを定義する場合は
// 引数なしコンストラクタも明示的に書く必要があります。
public Product() { }
}
}

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

サンプルアプリケーションでは、3つのタブに、異なるデータタイプを表示しています。

「バインドなし」タブ

「DataTable バインド」タブ

「BindingList バインド」タブ

DataGridView_AddRow.zip

※ サンプルアプリケーションは .NET 10 をターゲットとしています。

6. まとめ

DataGridView への行追加方法を状況別に整理します。

状況 行追加の方法
DataSource なし(バインドなし) dataGridView1.Rows.Add(値1, 値2, ...)
DataTable をバインド中 dataTable.Rows.Add(newRow)
BindingList をバインド中 bindingList.Add(new オブジェクト)

バインドしている場合に dataGridView1.Rows.Add() を呼ぶと InvalidOperationException が発生します。「DataSource を設定しているかどうか」を最初に確認するのが、実装ミスを防ぐ最短ルートです。

DataGridView 関連記事


💬 コメント