,NET Framework 4.8 の Windows Forms アプリで、 下の画像のように DataGridView の特定の列を ComboBox を使って表示する方法を書きます。
.NET 6, 8 でも Windows Forms アプリを作成できますが、[データ ソース]ウィンドウからドラッグ&ドロップして DataGridView 他のコードを自動生成させることはできませんので、お勧めしません。(Microsoft のドキュメント「ADO.NET アプリケーションに新しいデータ ソースを追加する (.NET Framework)」を見てください)
この記事では、Northwind サンプルデータベースの Products テーブルを使い、上の画像のように Category 列と Supplier 列を ComboBox を使って表示します。
Products テーブルを DataGridView に表示して更新操作ができるようにするだけなら、自分でコードは一行も書かなくても、Visual Studio のウィザードを使ってドラッグ&ドロップ操作だけで Windows Form アプリを作成できます。
ただし、Products テーブルの中の CategoryID, SupplierID は ID(数字)で表示されるので、そのままではユーザーにとっては分かりにくいです。
ID に代えて、名前を Categories, Suppliers テーブルから取得して表示した方がユーザーにとっては分かりやすいはずです。
さらにユーザーがデーターベースを編集・更新する場合は、ComboBox を使用してドロップダウン形式で一覧を表示し、その中からユーザーが選択できるようにするとさらにユーザーフレンドリーになると思います。
今回の例では、CategoryID, SupplierID 列に ComboBox を使い、各行の CategoryID, SupplierID に該当する名前 CategoryName, CompanyName を Categories, Suppliers テーブルから取得して ComboBox に表示するようにします。
Category 列の方は Visual Studio のウィザードを利用して、自力では一行もコードを書かずに ComboBox を実装してみます。
Supplier 列の方は自力でコードを書いて DataTable を作成し、それを ComboBox の DataSource に設定することにします。
以下にその手順を書きます。
(1) Visual Studio の[ファイル(F)]⇒[新しいプロジェクト(P)...]メニューから[Windows フォームアプリケーション]テンプレートを使って空のプロジェクトを作成する。
(2) ソリューションエクスプローラーでプロジェクトのルートを右クリック。[追加(D)]⇒[新しい項目(W)...]⇒[データセット]で適当な名前(例えば NorthwindDataSet.xsd)をつけて空の xsd ファイルを作成。(注:下の画像はステップ 12 まで進んだ時の完成済みのデータセットで、このステップの時点では何も表示されていません)
(3) ツールボックスから TableAdapter をドラッグ&ドロップすると TableAdapter 構成ウィザードが立ち上がる。
(4) クエリビルダで以下の SELECT クエリを作り、これをベースに DataTable + TableAdapter を作る。
SELECT ProductID, ProductName, CategoryID, SupplierID,
UnitPrice, Discontinued FROM Products
DataGridView に表示するとともに編集・更新操作を行うのはこれなので、TableAdapter 内に作成する更新系のメソッド等の生成オプションはフルにチェックを入れておく。
(5) TableAdapter 構成ウィザードでの操作が完了すると、ProductsDataTable と ProductsTableAdapter が自動生成されているはず。(上の NorthwindDataSet.xsd ファイルの画像で、左側の箱)
(6) Form1.cs を開きそのデザイン画面を表示する。データソースウィンドウを開くとその中に Products という項目があるはずなので、それを Form にドラッグ&ドロップする。
(7) 上のステップまでで、Products テーブルの表示、編集、更新ができるアプリが完成するはず。とりあえずこの段階で DataGridView への表示、レコードの INSERT, DELETE, UPDATE が問題なくできることを確認しておく。
(8) 上記が確認できたら、最初に Category の方を ComboBox で表示するための設定を行う。
(9) 自力でコードを書くのは必要最小限にするため、TableAdapter 構成ウィザードを利用して DataTable + TableAdapter を作り、これを利用する。
(10) NorthwindDataSet.xsd ファイルを開き、ツールボックスからもう一つ TableAdapter をドラッグ&ドロップする。
(11) TableAdapter 構成ウィザードが立ち上がるので、クエリビルダで以下の SELECT クエリを作り、これをベースに DataTable + TableAdapter を作成する。
SELECT CategoryID, CategoryName FROM Categories
こちらは、CategoryID に該当する CategoryName を ComboBox を使って表示するためのデーターソースとして利用するだけなので、TableAdapter に更新系のメソッドは不要。
(12) TableAdapter 構成ウィザードでの操作が完了すると、CategoriesDataTable と CategoriesTableAdapter が自動生成されているはず。(上の NorthwindDataSet.xsd ファイルの画像で、右側の箱)
(13) DataGridView の列の編集画面で、CatrgoryID 列の ColumnType を DataGridViewComboBoxColumn に変更する。
(14) 上の画面で、DataSource を[他のデータソース]⇒[プロジェクトデータソース]⇒[NorthwindDataSet]⇒[Catrgories]に設定すると、自動的に categoriesBindingSource が生成され、DataSource に設定される。
(15) 次に、DisplayMember を CategoryName に、ValueMember を CategoryID に設定する。
(16) ここまでの操作で、Category の方は ComboBox で表示され、編集する際は ComboBox をドロップダウンしてその中から選択して更新をかけることが可能になるはず。
(17) 次に、Supplier の方を ComboBox に表示するための設定を行う。こちらは TableAdapter 構成ウィザードを使用しないで、自力でコードを書いて DataTable を作り、それをデーターソースに利用してみる。
(18) Category の場合と同様に、DataGridView の列の編集画面で、SupplierID 列の ColumnType を DataGridViewComboBoxColumn に変更する。
(19) その先は自力でコードを書いて DataTable を作成し、それを DataGridViewComboBoxColumn の DataSource に設定する。
(29) Form1.cs のコード画面を開く。
(21) ADO.NET のライブラリを使い、Suppliers テーブルから SupplierID, CompanyName を取得し DataTable を作成するコードを追加する。具体例は以下のサンプルコードの CreateSuppliersTable を参照。
(22) Form1_Load メソッド(自動生成されているはず)の中に、上記 18 の手順で作成した DataGridViewComboBoxColumn の DataSource プロパティを CreateSuppliersTable メソッドが返す DataTable に、DisplayMember プロパティを "CompanyName" に、ValueMember プロパティを "SupplierID" に設定する。具体例は以下のサンプルコードを参照。
(23) 以上の操作で、一番上の画像のアプリが完成するはずです。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void productsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.productsBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.northwindDataSet);
}
private void Form1_Load(object sender, EventArgs e)
{
this.categoriesTableAdapter.Fill(this.northwindDataSet.Categories);
this.productsTableAdapter.Fill(this.northwindDataSet.Products);
// ここまでのコードは Visual Studio のウィザードで
// 自動生成される。
// ここから下のコードを自力で書いて追加する。
// DataSource に設定するのは Supplier の ComboBox に
// 表示するデータを含む DataTable。下のヘルパーメソッ
// ド CreateSuppliersTable で作成。
this.dataGridViewTextBoxColumn4.DataSource = CreateSuppliersTable();
this.dataGridViewTextBoxColumn4.DisplayMember = "CompanyName";
this.dataGridViewTextBoxColumn4.ValueMember = "SupplierID";
}
// Suppliers テーブルから SupplierID, CompanyName を抽出
// して DataTable を作るためのヘルパーメソッド。
private DataTable CreateSuppliersTable()
{
DataTable table = new DataTable("Suppliers");
table.Columns.Add(
new DataColumn("SupplierID", typeof(int)));
table.Columns.Add(
new DataColumn("CompanyName", typeof(string)));
string connString = Properties.Settings.Default
.NorthwindConnectionString;
string query = "SELECT SupplierID, CompanyName FROM Suppliers " +
"ORDER BY SupplierID";
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(query, conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
while (reader.Read())
{
DataRow row = table.NewRow();
row["SupplierID"] = reader.GetInt32(0);
row["CompanyName"] = reader.GetString(1);
table.Rows.Add(row);
}
}
}
}
}
return table;
}
}
}