DataGridView で行を追加する方法(サンプルあり)
📋 目次(クリックで展開)
- バインドなし:Rows.Add() で直接追加
- バインドあり(DataTable):DataTable に行を追加する
- バインドあり(BindingList):BindingList に行を追加する
- よくあるエラーと原因
- エラー①:InvalidOperationException(バインド中に Rows.Add を呼ぶ)
- エラー②:行を追加したのに画面に反映されない
- エラー③:追加した行が最下行の「*」行の後に入らない
- ソースコード
- サンプルコード
- サンプルアプリケーション
- 「バインドなし」タブ
- 「DataTable バインド」タブ
- 「BindingList バインド」タブ
- 6. まとめ
- 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 を呼ぶ)
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 バインド」それぞれのボタンで行を追加し、動作の違いを確認できます。
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 バインド」タブ

※ サンプルアプリケーションは .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 関連記事
- DataGridView:新規追加行の表示・非表示制御と注意点(AllowUserToAddRows)
- DataGridView で行削除の制御(サンプルあり)
- DataGridView に DataTable をバインドする(サンプルあり)
- DataGridView:List データをバインドする(サンプルあり)
- DataGridView 使い方ガイド【C# WinForms サンプルコード集】
💬 コメント