使用するデータベース
使用するAccessのデータベースは、ノートPCの一覧という簡単なデータベースで、1つのテーブルに「ID」「メーカー」「機種」「発売日」の4つのフィールドがあります。実際に使用するのは「ID」を除くフィールドで、それぞれ「テキスト型」で入力されており、発売日は「yyyy/mm/dd」という形式で保存されています。
選択されたリスト項目の取得
最初に、リストを選択したときにその項目を取得して、GcListBoxコンポーネントのステータスバーに表示する処理を作成します。ユーザーがリストをクリックすると、GcListBoxコンポーネントにはSelectedIndexChangedイベントが発生しますので、ここで処理を行います。
現在選択されている項目は、GcListBoxクラスの「SelectedItem」プロパティを使って取得できます。このプロパティは、選択されている項目をListItemオブジェクトで返してきます。プログラムでは、単一の項目しか選択できないように設定していますが、GcListBoxコンポーネントは複数選択も可能で、その場合選択項目はすべてListItemオブジェクトとして返されます。
後は、このListItemオブジェクトのSubItemsプロパティで、参照したいフィールドをインデックス番号で指定して取り出します。
Dim li As ListItem = GcListBox1.SelectedItem Me.GcListBox1.StatusBar.Text = li.SubItems(0).Value
ListItem li = gcListBox1.SelectedItem; gcListBox1.StatusBar.Text = li.SubItems[0].Value
後は、必要な列の値をSubItemsプロパティをつなげていけば、選択した行のデータを取得できます。
ただし、このSelectedIndexChangedイベントがハンドルされている時にフォームを閉じると、以下のプロパティ値でイベントハンドラが呼び出されるようになっています。
| プロパティ | 値 |
| SelectedIndexプロパティ | -1 |
| SelectedItemプロパティ | Nothing |
このままだと、NothingとなっているSelectedItemプロパティに対してSubItemsプロパティを参照することになってしまい、フォームを閉じる際に「オブジェクトが参照されていない」というエラーメッセージが出てしまいます。
この問題を回避するために、SelectedIndexプロパティを参照しこの値が0以上だった場合のみSubItemsプロパティを参照するようにします。
Private Sub GcListBox1_SelectedIndexChanged( _ ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles GcListBox1.SelectedIndexChanged If (GcListBox1.SelectedIndex < 0) Then Return End If Dim li As ListItem = GcListBox1.SelectedItem Me.GcListBox1.StatusBar.Text = li.SubItems(0).Value & _ " : " & li.SubItems(1).Value & _ " : " & li.SubItems(2).Value End Sub
private void gcListBox1_SelectedIndexChanged(object sender, EventArgs e) { if(gcListBox1.SelectedIndex < 0){ return; } ListItem li = gcListBox1.SelectedItem; gcListBox1.StatusBar.Text = li.SubItems[0].Value + " : " + li.SubItems[1].Value + " : " + li.SubItems[2].Value; } }
リスト内を検索する処理
冒頭でも述べましたが、GcListBoxコンポーネントはリスト内を検索して、データを取り出す機能を持っています。
そこで、この機能を使い日付でリスト内のデータを検索し、一致するデータをもう1つのGcListBoxコンポーネントで表示する機能を組み込んでみます。
FindStringメソッドとMatchedListItemCollection
検索を行うには、FindStringメソッドを使用します。検索用のメソッドは3つありますが、FindStringメソッドは文字列を検索条件に設定できます。このプログラムでは、日付を文字列で入力していますから、FindStringメソッドで検索をします。
引数は2つで、最初の引数に検索条件となる文字列を、2番目の引数に検索を行う列番号を指定します。ここでは、GcDateコンポーネントで入力された日付を元に、リストの3番目の列を対象に検索を行います。GcDateコンポーネントのTextプロパティを参照すると、選択された日付を文字列で取得することができますので、これをFindStringメソッドの第1引数に設定します。
一致するデータが見つかると、FindStringメソッドはそのデータをMatchedListItemCollectionオブジェクトで返してきます。複数のデータが見つかれば、次々とこのMatchedListItemCollectionオブジェクトに追加されていくことになります。
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim matchedItem As MatchedListItemCollection Dim item As ListItem Dim additem As ListItem 'FindObjectメソッドを使って検索 ' 検索結果はMatchedListItemCollectionに格納される matchedItem = GcListBox1.FindString(Me.GcDate1.Text, 2)
private void button1_Click(object sender, EventArgs e) { MatchedListItemCollection matchedItem; ListItem additem; //FindObjectメソッドを使って検索 // 検索結果はMatchedListItemCollectionに格納される matchedItem = gcListBox1.FindString(gcDate1.Text, 2);
検索結果のリスト化
このMatchedListItemCollectionのCountプロパティを調べることで、検索結果があるかどうかを知ることができますので、検索結果がある場合のみ、もう1つのGcListBoxコンポーネントにリストとして組み込みます。
まず、すでにリストがある場合はこれを削除します。GcListBoxクラスのItemsコレクションのClearメソッドを使用すると、GcListBoxコンポーネントに組み込まれているリストをすべて削除します。
次に、For Eachステートメントで、MatchedListItemCollection内のオブジェクトにアクセスし、検索結果1レコード分のフィールド1つ1つをSubItemオブジェクトとして作成し、これをまとめてListItemオブジェクトにします。そして、できあがったListItemオブジェクトをGcListBoxコンポーネントに組み込みます。
この処理を、MatchedListItemCollection内のすべてのオブジェクト(すべてのレコード)に対して行い、検索結果のデータを全部リスト化していきます。
'検索結果があるかどうかを判別
If matchedItem.Count = 0 Then
MessageBox.Show("一致するデータはありません", _
"検索結果", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Else
'すでにリストがある場合は一度削除する
Me.GcListBox2.Items.Clear()
For Each item In matchedItem
'データ1件の各列データをそれぞれSubItemオブジェクトにする
Dim sbitem1 As New SubItem(item.SubItems(0).Value.ToString)
Dim sbitem2 As New SubItem(item.SubItems(1).Value.ToString)
Dim sbitem3 As New SubItem(item.SubItems(2).Value.ToString)
'SubItemオブジェクトをまとめてListItemオブジェクトにする
additem = New ListItem(sbitem1, sbitem2, sbitem3)
'できあがったListItemオブジェクトを
'GcListBoxコンポーネントに組み込む
GcListBox2.Items.Add(additem)
'検索されたデータの数だけListItemオブジェクトが作られ
'GcListBoxコンポーネントに組み込まれる
Next
End If
End Sub
//検索結果があるかどうかを判別
if(matchedItem.Count == 0){
MessageBox.Show("一致するデータはありません",
"検索結果",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}else{
//すでにリストがある場合は一度削除する
gcListBox2.Items.Clear();
foreach(ListItem item in matchedItem){
//データ1件の各列データをそれぞれSubItemオブジェクトにする
SubItem sbitem1 = new SubItem(item.SubItems[0].Value);
SubItem sbitem2 = new SubItem(item.SubItems[1].Value);
SubItem sbitem3 = new SubItem(item.SubItems[2].Value);
//SubItemオブジェクトをまとめてListItemオブジェクトにする
additem = new ListItem(sbitem1, sbitem2, sbitem3);
//できあがったListItemオブジェクトを
//GcListBoxコンポーネントに組み込む
gcListBox2.Items.Add(additem);
//検索されたデータの数だけListItemオブジェクトが作られ
//GcListBoxコンポーネントに組み込まれる
}
}
}
まとめ
ベースとなるリストから別のリストを作成することはよくあることですが、データベースからクエリで取得したデータに対してリスト上で検索・抽出ができるとなると、改めてデータベースに対してクエリを実行する必要がありませんから、処理速度も上がりサーバに対する負荷も少なくなります。
このような点を考えると、このGcListBoxコンポーネントはかなり使い勝手がよいコンポーネントだと思います。


