このサンプルコードは、DataRelationを使って3つのコンボボックスを順に絞り込んでいく方法です。
データベースはSQLServerについてるAdventureWorksを使用しています。
メリットとしてはデータをすべて取り込んだ後のコンボボックスのデータの内容のスピードは速いと思います。
デメリットとしてはテーブルデータをすべて取り込むのでメモリを大きく必要とするのと、必要のないデータも取得するのでネットワークトラフィックが増えたり、最初のロードの時間がかかってしまうことです。
C#
public partial class Form1 : Form { DataSet ds = new DataSet(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //SQL Serverへの接続情報用変数 SqlConnectionStringBuilder connBldr = new SqlConnectionStringBuilder(); //ここではローカルのSQL Serverを指定しています。 connBldr.DataSource = @".\SQLEXPRESS"; //AdventureWorksを使用します。 connBldr.InitialCatalog = "AdventureWorks"; //Windowsアカウント情報を利用します。 connBldr.IntegratedSecurity = true; //SQL Serverへの接続用変数 SqlConnection conn = new SqlConnection(connBldr.ConnectionString); //SQLコマンド用変数 SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; //ComboBox1用のSQL cmd.CommandText = "SELECT CustomerID FROM Sales.Customer ORDER BY CustomerID"; SqlDataAdapter ad = new SqlDataAdapter(); ad.SelectCommand = cmd; ds.Tables.Add("Customer"); ad.Fill(ds.Tables["Customer"]); //ComboBox2用のSQL cmd.CommandText = "SELECT CustomerID,SalesOrderID FROM Sales.SalesOrderHeader " + "ORDER BY CustomerID,SalesOrderID"; ds.Tables.Add("SalesOrderHeader"); ad.Fill(ds.Tables["SalesOrderHeader"]); //ComboBox2用のSQL cmd.CommandText = "SELECT SalesOrderID,SalesOrderDetailID FROM Sales.SalesOrderDetail " + "ORDER BY SalesOrderID,SalesOrderDetailID"; ds.Tables.Add("SalesOrderDetail"); ad.Fill(ds.Tables["SalesOrderDetail"]); this.comboBox1.DisplayMember = "CustomerID"; this.comboBox1.ValueMember = "CustomerID"; //DisplyaMemberやValueMemberを設定してからDataSourceを設定する this.comboBox1.DataSource = ds.Tables[0]; //ComboBox2のDataSourceは、ComboBox1が選択された時に設定する this.comboBox2.DisplayMember = "SalesOrderID"; this.comboBox2.ValueMember = "SalesOrderID"; //ComboBox3のDataSourceは、ComboBox2が選択された時に設定する this.comboBox3.DisplayMember = "SalesOrderDetailID"; this.comboBox3.ValueMember = "SalesOrderDetailID"; //ここでDataRelationを設定することによって、絞り込み処理を簡単にできるようになる。 ds.Relations.Add(new DataRelation("Customer", ds.Tables[0].Columns["CustomerID"], ds.Tables[1].Columns["CustomerID"])); ds.Relations.Add(new DataRelation("SalesOrder", ds.Tables[1].Columns["SalesOrderID"], ds.Tables[2].Columns["SalesOrderID"])); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { //項目が選択されており、かつ有効な値かどうかチェックする if (comboBox1.SelectedIndex > -1 && comboBox1.SelectedValue.ToString() != "") { //ComboBox1で選択された値にマッチする行を抽出 DataRow[] drs = ds.Tables[0].Select("CustomerID = " + comboBox1.SelectedValue); //マッチするものが有ったかチェック if (drs.Length > 0) { foreach (DataRow dr in drs) { //DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出 DataRow[] drs2 = dr.GetChildRows("Customer"); //マッチする行があったかチェック if (drs2.Length > 0) { //ComboBox2を有効にしてデータソースを設定する comboBox2.Enabled = true; comboBox2.DataSource = drs2.CopyToDataTable(); } else { comboBox2.SelectedIndex = -1; comboBox2.Enabled = false; comboBox3.SelectedIndex = -1; comboBox3.Enabled = false; } } } } } private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) { //項目が選択されており、かつ有効な値かどうかチェックする if (comboBox2.SelectedIndex > -1 && comboBox2.SelectedValue.ToString() != "") { //ComboBox2で選択された値にマッチする行を抽出 DataRow[] drs = ds.Tables[1].Select("SalesOrderID = " + comboBox2.SelectedValue); //マッチするものが有ったかチェック if (drs.Length > 0) { foreach (DataRow dr in drs) { //DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出 DataRow[] drs2 = dr.GetChildRows("SalesOrder"); //マッチする行があったかチェック if (drs2.Length > 0) { //ComboBox3を有効にしてデータソースを設定する comboBox3.Enabled = true; comboBox3.DataSource = drs2.CopyToDataTable(); } else { comboBox3.SelectedIndex = -1; comboBox3.Enabled = false; } } } } } }
VB.NET
Imports System.Data.SqlClient Imports System.Data Public Class Form1 Dim ds As DataSet = New DataSet() Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'SQL Serverへの接続情報用変数 Dim connBldr As SqlConnectionStringBuilder = New SqlConnectionStringBuilder() 'ここではローカルのSQL Serverを指定しています。 connBldr.DataSource = "." 'AdventureWorksを使用します。 connBldr.InitialCatalog = "AdventureWorks" 'Windowsアカウント情報を利用します。 connBldr.IntegratedSecurity = True 'SQL Serverへの接続用変数 Dim conn As SqlConnection = New SqlConnection(connBldr.ConnectionString) 'SQLコマンド用変数 Dim cmd As SqlCommand = New SqlCommand() cmd.Connection = conn 'ComboBox1用のSQL cmd.CommandText = "SELECT CustomerID FROM Sales.Customer ORDER BY CustomerID" Dim ad As SqlDataAdapter = New SqlDataAdapter() ad.SelectCommand = cmd ds.Tables.Add("Customer") ad.Fill(ds.Tables("Customer")) 'ComboBox2用のSQL cmd.CommandText = "SELECT CustomerID,SalesOrderID FROM Sales.SalesOrderHeader ORDER BY CustomerID,SalesOrderID" ds.Tables.Add("SalesOrderHeader") ad.Fill(ds.Tables("SalesOrderHeader")) 'ComboBox3用のSQL cmd.CommandText = "SELECT SalesOrderID,SalesOrderDetailID FROM Sales.SalesOrderDetail ORDER BY SalesOrderID,SalesOrderDetailID" ds.Tables.Add("SalesOrderDetail") ad.Fill(ds.Tables("SalesOrderDetail")) Me.ComboBox1.DisplayMember = "CustomerID" Me.ComboBox1.ValueMember = "CustomerID" 'DisplyaMemberやValueMemberを設定してからDataSourceを設定する Me.ComboBox1.DataSource = ds.Tables(0) 'ComboBox2のDataSourceは、ComboBox1が選択された時に設定する Me.ComboBox2.DisplayMember = "SalesOrderID" Me.ComboBox2.ValueMember = "SalesOrderID" 'ComboBox3のDataSourceは、ComboBox2が選択された時に設定する Me.ComboBox3.DisplayMember = "SalesOrderDetailID" Me.ComboBox3.ValueMember = "SalesOrderDetailID" 'ここでDataRelationを設定することによって、絞り込み処理を簡単にできるようになる。 ds.Relations.Add(New DataRelation("Customer", ds.Tables(0).Columns("CustomerID"), ds.Tables(1).Columns("CustomerID"))) ds.Relations.Add(New DataRelation("SalesOrder", ds.Tables(1).Columns("SalesOrderID"), ds.Tables(2).Columns("SalesOrderID"))) End Sub Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged '項目が選択されており、かつ有効な値かどうかチェックする If ComboBox1.SelectedIndex > -1 And Not ComboBox1.SelectedValue.ToString() = "" Then 'ComboBox1で選択された値にマッチする行を抽出 Dim drs() As DataRow = ds.Tables(0).Select("CustomerID = " & ComboBox1.SelectedValue.ToString()) 'マッチするものが有ったかチェック If drs.Length > 0 Then For Each dr As DataRow In drs 'DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出 Dim drs2() As DataRow = dr.GetChildRows("Customer") 'マッチする行があったかチェック If drs2.Length > 0 Then 'ComboBox2を有効にしてデータソースを設定する ComboBox2.Enabled = True ComboBox2.DataSource = drs2.CopyToDataTable() Else ComboBox2.SelectedIndex = -1 ComboBox2.Enabled = False ComboBox3.SelectedIndex = -1 ComboBox3.Enabled = False End If Next End If End If End Sub Private Sub ComboBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox2.SelectedIndexChanged '項目が選択されており、かつ有効な値かどうかチェックする If ComboBox2.SelectedIndex > -1 And Not ComboBox2.SelectedValue.ToString() = "" Then 'ComboBox2で選択された値にマッチする行を抽出 Dim drs() As DataRow = ds.Tables(1).Select("SalesOrderID = " & ComboBox2.SelectedValue.ToString()) 'マッチするものが有ったかチェック If drs.Length > 0 Then For Each dr As DataRow In drs 'DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出 Dim drs2() As DataRow = dr.GetChildRows("SalesOrder") 'マッチする行があったかチェック If drs2.Length > 0 Then 'ComboBox3を有効にしてデータソースを設定する ComboBox3.Enabled = True ComboBox3.DataSource = drs2.CopyToDataTable() Else ComboBox3.SelectedIndex = -1 ComboBox3.Enabled = False End If Next End If End If End Sub End Class