[C#][Windows Formsアプリ][ComboBox] DataSource・DisplayMember・ValueMemberプロパティでデータバインドを行う

スポンサーリンク

はじめに

コンボボックスを「文字列の並び」から一歩進めて、データ付きリストとして扱う鍵が
DataSourceDisplayMemberValueMemberの3つです。
画面に見せる値(表示名)と、内部で扱う値(ID等)を分離でき、業務アプリで必須の知識になります。

 

各プロパティの役割

プロパティ 意味 例(都市マスタ)
DataSource バインド元(配列・List<T>・DataTable・BindingSource)を指定 List<City> / DataTable
DisplayMember 画面に表示するプロパティ名(列名) "Name" → 「東京」
ValueMember 内部的に扱う値のプロパティ名(列名) "Id" → 1
💡 ポイント: ユーザーが「東京」を選んでも、アプリは SelectedValue から Id=1 を扱えます。表示と内部値を綺麗に分離できます。

 

List<T> を使った基本例(最もシンプル)

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var cities = new List<City>
{
    new City { Id = 1, Name = "東京" },
    new City { Id = 2, Name = "大阪" },
    new City { Id = 3, Name = "名古屋" },
    new City { Id = 4, Name = "福岡" },
};

comboBox1.DataSource    = cities;
comboBox1.DisplayMember = "Name"; // 表示
comboBox1.ValueMember   = "Id";   // 内部値

// 既定選択(ID=2 → 大阪)
comboBox1.SelectedValue = 2;

// 取得:ユーザーが選んだIDと表示名
int    id   = (int)comboBox1.SelectedValue;
string name = comboBox1.Text; // または ((City)comboBox1.SelectedItem).Name

 

DataTable を使った例(DB連携の定番)

var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Rows.Add(1, "営業部");
dt.Rows.Add(2, "開発部");
dt.Rows.Add(3, "総務部");

comboBoxDept.DataSource    = dt;
comboBoxDept.DisplayMember = "Name";
comboBoxDept.ValueMember   = "Id";

comboBoxDept.SelectedValue = 3; // 総務部を選択

int selectedDeptId = (int)comboBoxDept.SelectedValue;

 

BindingSource を使う(並べ替え・フィルタが楽)

var bs = new BindingSource();
bs.DataSource = cities;                    // List<City> や DataTable を設定
// DataTableの場合は bs.Sort / bs.Filter が使える
// 例: bs.Sort = "Name ASC";

comboBox1.DataSource    = bs;
comboBox1.DisplayMember = "Name";
comboBox1.ValueMember   = "Id";
🔁 データの差し替え・再読込 は BindingSource 経由がシンプル。
bs.DataSource = 新しいリスト; とするだけで UI が更新されます。

 

SelectedValue と SelectedItem の関係

  • SelectedValueValueMember で指定した値(ID等)。保存・検索に最適。
  • SelectedItem … 選択されたオブジェクト(行)。必要に応じてプロパティへアクセス。
  • Text … 表示テキスト(= DisplayMember)。
// 例:選択をIDで制御
comboBox1.SelectedValue = 4;        // ID=4に対応する行が選択される
int id = (int)comboBox1.SelectedValue;
var row = comboBox1.SelectedItem;    // City or DataRowView など
string display = comboBox1.Text;     // 表示名

 

依存(カスケード)コンボボックスの基本パターン

「都道府県 → 市区町村」のように、親の選択で子の候補を絞る例:

// 親:都道府県
comboPref.DataSource    = prefs; // List<Pref> { Id, Name }
comboPref.DisplayMember = "Name";
comboPref.ValueMember   = "Id";

// 子:市区町村(BindingSourceで差し替え)
var bsCity = new BindingSource();
comboCity.DataSource    = bsCity;
comboCity.DisplayMember = "Name";
comboCity.ValueMember   = "Id";

comboPref.SelectedValueChanged += (_, __) =>
{
    int prefId = (int)comboPref.SelectedValue;
    var citiesInPref = allCities.Where(c => c.PrefId == prefId).ToList();
    bsCity.DataSource = citiesInPref;
    comboCity.SelectedIndex = citiesInPref.Count > 0 ? 0 : -1;
};

 

よくある落とし穴と対策

  • DisplayMember / ValueMember の名前が間違っている:存在するプロパティ(列)名を設定。先に DataSource を設定し、その後に Member を設定すると安全。
  • SelectedValue の型不一致int なのに "1" を代入する等は選択されません。型を合わせる。
  • 表示順を並べ替えたい:DataTable + BindingSource の Sort、または List を OrderBy してから DataSource に設定。
  • Items と DataSource の併用:同時使用は不可。バインド中は Items.Add() せず、元データを更新して再バインド。
  • DropDownStyle=DropDownList での入力:自由入力不可。検索性は AutoCompleteMode/Source で補う。

 

便利レシピ集

表示列は同じだが、内部値だけ変えたい

comboBox.DisplayMember = "Name";
comboBox.ValueMember   = "Code";   // 例: "TOKYO" / "OSAKA"

列名が取りづらい匿名型でもOK

comboBox.DataSource = new[]
{
    new { Id = 1, Name = "小計" },
    new { Id = 2, Name = "消費税" },
    new { Id = 3, Name = "合計" }
};
comboBox.DisplayMember = "Name";
comboBox.ValueMember   = "Id";

前回選んだIDを復元

int lastId = Properties.Settings.Default.LastCityId;
comboBox1.SelectedValue = lastId;

 

まとめ

  • DataSource で一覧の元データを渡し、DisplayMemberValueMember見せ方と内部値を分離する。
  • 選択制御・保存・検索は SelectedValue を中心に。
  • 更新や並べ替えは BindingSource を介すと管理が楽。
  • 型・プロパティ名・設定順序のミスが定番。まずは DataSource → Member の順で堅く組む。
Please follow and like us:

コメント

タイトルとURLをコピーしました