このサンプルコードは、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
