DataGridView への行追加は、DataSource にバインドしているかどうかで方法が変わります。
バインドなしの場合は dataGridView1.Rows.Add() で直接追加できますが、バインドしている場合に同じコードを書くと実行時エラーになります。本記事では、状況別の行追加方法と、よくあるエラーの原因・対処法を C# サンプルコードとともに解説します。
目次
バインドなし:Rows.Add() で直接追加
DataSource を設定せず、列を手動で追加している場合は Rows.Add() で直接行を追加できます。
C#
// 値を直接指定して追加(列の順番に対応)
dataGridView1.Rows.Add("値1", "値2", "値3");
列数が多い場合や、追加後にセル値を個別に設定したい場合は、行オブジェクトを先に作ってから追加する方法が読みやすいです。
C#
// 行オブジェクトを作ってから追加する 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 の表示に自動的に反映されます。
C#
// DataTable に新しい行を追加する(パターン①:値を直接指定) DataRow newRow = _dataTable.NewRow(); newRow["ID"] = 4; newRow["Name"] = "たろう"; newRow["Age"] = 30; _dataTable.Rows.Add(newRow);
列の順番が決まっていて簡潔に書きたい場合は、値を直接渡す書き方も使えます。
C#
// DataTable に新しい行を追加する(パターン②:列順に値を指定) _dataTable.Rows.Add(4, "たろう", 30);
ポイント:
_dataTableはフィールド変数として保持しておく必要があります。Form_Load内でローカル変数に DataTable を作ってDataSourceに設定するだけでは、後から行を追加できません。
バインドあり(BindingList):BindingList に行を追加する
BindingList<T> をバインドしている場合は、リストにオブジェクトを追加するだけで DataGridView に反映されます。
C#
// BindingList にオブジェクトを追加する
_products.Add(new Product { ID = 4, Name = "ぶどう", Price = 500 });
BindingList<T> は変更通知を持っているため、Add() を呼ぶだけで自動的に画面が更新されます。DataTable と違い、型安全に扱えるのが利点です。
よくあるエラーと原因
エラー①:InvalidOperationException(バインド中に Rows.Add を呼ぶ)
System.InvalidOperationException: 'DataSource が設定されている場合、行をプログラムで DataGridView に追加することはできません。'
原因: DataSource にバインドした状態で dataGridView1.Rows.Add() を呼んでいます。
対処: DataTable や BindingList など、バインドしているデータソース側に行を追加してください。
エラー②:行を追加したのに画面に反映されない
原因: DataTable をローカル変数で作成してバインドしたため、後からアクセスできていません。
C#
// 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 をフィールド変数として宣言して保持してください。
C#
// 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 を設定してください。
C#
dataGridView1.AllowUserToAddRows = false;
新規追加行の詳細な制御については、「DataGridView:新規追加行の表示・非表示制御と注意点」を参照してください。
サンプルコード
3つの行追加パターンをタブ切り替えで確認できるサンプルアプリです。「バインドなし」「DataTable バインド」「BindingList バインド」それぞれのボタンで行を追加し、動作の違いを確認できます。
C#
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() { }
}
}
サンプルアプリケーション

※ サンプルアプリケーションは .NET 10 をターゲットとしています。
6. まとめ
DataGridView への行追加方法を状況別に整理します。
| 状況 | 行追加の方法 |
|---|---|
| DataSource なし(バインドなし) | dataGridView1.Rows.Add(値1, 値2, ...) |
| DataTable をバインド中 | dataTable.Rows.Add(newRow) |
| BindingList をバインド中 | bindingList.Add(new オブジェクト) |
バインドしている場合に dataGridView1.Rows.Add() を呼ぶと InvalidOperationException が発生します。「DataSource を設定しているかどうか」を最初に確認するのが、実装ミスを防ぐ最短ルートです。