DataGridView:List データをバインドする(サンプルあり)

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

C# の Windows Forms 開発において、独自クラスのオブジェクトを格納した通常の List<T> のデータを DataGridView に表示させたいケースがあります。

一度画面を表示したらデータの追加や削除が行われない「読み取り専用」のような画面であれば、軽量な List<T> をそのままバインドする手法は非常にシンプルで実用的です。しかし、通常の List<T> をデータソースにする場合には、通知機能の面でいくつかの重要な制限が存在します。

今回は、通常の List<T> データを DataGridView にバインドする実装手順と、その際に把握しておくべき制限事項、および変更を画面に強制反映させる方法について解説します。

Listデータをバインドする基本実装

DataGridView は DataSource プロパティに List<T> を渡すだけで、そのクラスの public なプロパティ(get; set; を持つメンバ)を自動的に解析して列を生成してくれます。

以下は、商品情報を管理する Product クラスの List<Product> を作成し、DataGridView にバインドするコード例です。

Form1.cs

Form1.cs
namespace DataGridView_Bind_List
{
public partial class Form1 : Form
{
// 通常の List<T> を定義
private List<Product> _productList = new List<Product>();
public Form1()
{
InitializeComponent();
InitializeDataGridView();
}
private void InitializeDataGridView()
{
// 1. テストデータの準備
_productList.Add(new Product("P001", "ノートパソコン", 120000));
_productList.Add(new Product("P002", "USBメモリ", 2500));
// 2. DataGridViewのDataSourceにListを直接バインド
// クラスのプロパティ(Code, Name, Price)に合わせた列が自動生成されます
dataGridView1.DataSource = _productList;
// 見栄えの調整
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
}
/// <summary>
/// DataGridViewに表示するデータを保持するモデルクラス
/// </summary>
public class Product
{
// 通常の変数(フィールド)ではなく、必ずプロパティ(get; set;)として定義します
public string Code { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public int Price { get; set; }
public Product(string code, string name, int price)
{
Code = code;
Name = name;
Price = price;
}
}
}

ソースコード

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

DataGridView_Bind_List.zip
※ サンプルアプリケーションは、.NET 10 をターゲットに作成しています。

実行結果

List をバインドする際の制限

通常の List<T> を使用する場合、実務上の設計で注意しなければならないのが「データの変更が画面に自動反映されない」という制限です。

通常の List<T> は、コード側で _productList.Add(...)_productList.Remove(...) を実行して要素を増減させても、それを外部(DataGridView)へ伝える「変更通知イベント」を持っていません。そのため、バックグラウンドのリストの中身が変わっても、DataGridView の画面表示は変化しません。

制限を解決して画面を強制更新する手順

もし List<T> を使ったままで、ボタンクリックなどのタイミングでデータの追加・削除を画面に反映させたい場合は、以下のようにデータソースを一度クリアしてから再接続(再バインド)するという手順を踏む必要があります。

/// <summary>
/// 「商品追加」ボタンのクリックイベント
/// </summary>
private void btnAddProduct_Click(object sender, EventArgs e)
{
// 1. コード側で通常の List<T> にデータを追加
_productList.Add(new Product("P003", "液晶モニター", 35000));
// ❌ 通常のListは通知機能がないため、これだけでは画面が更新されません
// ⭕【対策】データソースを一度リセットし、再バインドすることで強制的に画面を更新します
dataGridView1.DataSource = null;
dataGridView1.DataSource = _productList;
}

このように、データの変更があるたびに DataSource = null; を挟んで再設定を行うのが、通常の List<T> を運用する際の定石となります。

より高度な画面制御が必要な場合(BindingListへの移行)

マスタ登録画面や伝票入力画面など、「ユーザーの操作やコードの処理によって、グリッドの行が激しく追加・削除・編集される」というシナリオにおいては、上記の再バインド(DataSource = null)を繰り返すアプローチはコードが煩雑になり、スクロール位置の初期化や選択行のバグを誘発しやすくなります。

もし、リストへの操作と画面の表示を完全にリアルタイム連動させたい、あるいは行ごとのプロパティ変更まで細かく検知させたいという場合は、List<T> ではなく、通知機能を標準搭載した BindingList<T> を最初から選択するのがベストです。

BindingList<T> を使用した、より堅牢でスムーズな双方向データバインドの実装手順については、以下の別記事にて詳しく解説していますので、要件に応じてこちらも併せて参照してください。

DataGridViewにBindingListをデータバインドして自動更新する方法

まとめ

今回は、独自のオブジェクトを格納した通常の List<T> データを DataGridView にバインドする手順と、その特性について解説しました。
静的なデータ表示や、一度読み込んだら更新が不要なダッシュボード画面などでは、List<T> によるバインドは軽量で非常に扱いやすい選択肢です。

  • 表示クラスのメンバは必ずプロパティ({ get; set; })で設計する
  • 通常の List<T> にはデータの変更通知機能がないため、追加・削除は自動反映されない
  • データを更新した場合は DataSource = null; を経由して再バインドをかける
  • 動的なデータ追加・削除がメインの画面では、上位互換である BindingList<T> の利用を検討する

実装する画面の「データが変化する頻度」に応じて、最適なコレクションのバインド手法を選択してください。


💬 コメント