DataGridView:BindingList をバインドする(サンプルあり)
DataGridView に独自のクラス(オブジェクト)のリストを表示させたい場合、標準の List<T> をデータソースに指定すると、コード側で行を追加・削除しても画面が自動的に更新されないという問題に遭遇します。
オブジェクトのコレクションを DataGridView 側と常に自動で連動させたい場合に、最も標準的で最適なデータソースとなるのが BindingList<T> です。
今回は、DataGridView に BindingList<T> をバインドしてデータを表示する基本手順と、そのまま動かせるシンプルなサンプルコードについて解説します。
BindingList をデータソースにするメリット
「DataTable をバインドする方法」に慣れていると、C# の独自クラス(オブジェクト)をバインドする手順に最初は戸惑うかもしれません。しかし、オブジェクトバインドには実務上非常に大きなメリットがあります。
DataTable を使用する場合、列の指定などを「文字列(dt.Rows[0]["Name"])」で行うためタイポによるバグが起きやすいですが、独自クラスであれば「型安全(item.Name)」にデータを扱えるようになります。
そして、データソースに BindingList<T> を選択することで、「コード側でリストに行を追加・削除した際、DataGridView 側にもその変更が自動的に通知され、画面が即座に再描画される」 という双方向の連動が最小限のコードで実現します。
実装コード
以下は、独自に作成したデータモデル(MemberModel)の BindingList<T> を DataGridView のデータソースに設定し、ボタンクリックで行を動的に追加するサンプルコードです。
Form1.cs(画面側の処理)
using System.ComponentModel;
namespace DataGridView_Bind_BindingList{ public partial class Form1 : Form { // 1. BindingListの宣言(クラスのメンバ変数として保持します) private BindingList<MemberModel> _members = new();
public Form1() { InitializeComponent(); InitializeDataGridView();
btnAdd.Click += btnAdd_Click; }
private void InitializeDataGridView() { // 初期データをリストに追加 _members.Add(new MemberModel("M001", "山田 太郎", "開発部")); _members.Add(new MemberModel("M002", "佐藤 花子", "営業部"));
// 2. DataGridView の DataSource に BindingList を指定 dataGridView1.DataSource = _members;
// (任意)列幅を画面いっぱいに自動調整する設定 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; }
// 「行追加」ボタンのクリックイベント private void btnAdd_Click(object? sender, EventArgs e) { // 3. データソース(リスト)に対象を追加するだけで、画面側も自動的に行が増えます _members.Add(new MemberModel("M003", "鈴木 一郎", "総務部")); } }
/// <summary> /// グリッドに表示するデータを保持するシンプルなモデルクラス /// </summary> public class MemberModel { public string Id { get; set; } public string Name { get; set; } public string Department { get; set; }
public MemberModel(string id, string name, string department) { Id = id; Name = name; Department = department; } }}サンプルアプリケーション
DataGridView_Bind_BindingList.zip
※ サンプルアプリケーションは、.NET 9 をターゲットに作成しています。
注意点:オブジェクト内部の値変更について
「BindingList を使えば、データと画面のすべてが自動的に同期される」と思いがちですが、実はオブジェクト内部のプロパティの値を直接書き換える場合には、もう一つの仕掛けが必要になります。
BindingList<T> が標準で自動検知して画面に通知してくれるのは、あくまで「要素そのものの追加(Add)や削除(Remove)」のタイミングのみです。
例えば、以下のように既存の行のデータをコード側で直接書き換えた場合、これだけでは DataGridView のセル表示は自動更新されません。
// これだけでは画面の表示は古いまま変わらない_members[0].Name = "新しい名前に変更";もし、オブジェクト内部のプロパティ変更(値の更新)までリアルタイムに画面に連動させたい場合は、データモデル側に INotifyPropertyChanged インターフェースを実装する必要があります。
この「値が反映されない問題」の具体的な原因と正しい対策については、別記事「DataGridView でデータ変更が画面に反映されない原因と解決方法」にて詳しく解説していますので、実務で値を書き換える要件がある場合はあわせてご参照ください。
まとめ
今回は、DataGridView に BindingList<T> をバインドしてデータを表示する最もシンプルで標準的な手順について解説しました。
DataTable によるバインドと同様に、この BindingList によるオブジェクトバインドも、一度書き方を覚えてしまえば Windows Forms 開発における非常に強力な武器になります。
データの管理をすべてコード(ロジック)側で行い、画面(UI)がそれに自動で追従する形を作ることで、コードの視認性やメンテナンス性は格段に向上します。
C# のクラスオブジェクトをベースにした、型安全なグリッド画面開発の参考になれば幸いです。
💬 コメント