.NET Frameworkのクラスライブラリに含まれるSystem.Windows.Forms.ListBoxクラスは、VB6以前のListBoxが機能拡張されたものと言えます。 というのも、多くの動作はそのままで様々な機能が追加されているからです。 ここではそのような追加された機能を見ていきたいと思います。

§1 選択されているアイテムとインデックスの取得

まずは、選択されているアイテムと、そのインデックスの取得について見てみます。 リストボックスのアイテムの内、選択されているものはSelectedItemsプロパティ、そのインデックスはSelectedIndicesプロパティによって取得できます。 これらのプロパティは IEnumerableインターフェイスを実装したコレクションになっているので、For Each文によって列挙できます。

次のサンプルは、インデックスと同じ値を振った文字列アイテムをリストボックスに追加し、選択されているアイテムが変わったときに生じるSelectedValueChangedイベントで選択されているアイテムとそのインデックスを列挙しています。

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "
#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        With listBoxItems

            ' 選択モード
            .SelectionMode = SelectionMode.MultiExtended

            With .Items

                Dim i As Integer

                For i = 0 To 9

                    .Add("Item" + i.ToString())

                Next

            End With

        End With

    End Sub

    Private Sub listBoxItems_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles listBoxItems.SelectedValueChanged

        ' 選択されているアイテム一覧を表示
        Dim o As Object

        listBoxSelectedItems.Items.Clear()

        For Each o In listBoxItems.SelectedItems

            listBoxSelectedItems.Items.Add(o)

        Next

        ' 選択されているアイテムのインデックス一覧を表示
        Dim i As Integer

        listBoxSelectedIndices.Items.Clear()

        For Each i In listBoxItems.SelectedIndices

            listBoxSelectedIndices.Items.Add(i)

        Next

    End Sub

End Class
実行結果

§2 様々な型のアイテムの追加

リストボックスには、様々な型のアイテムを追加することもできます。 というのも、アイテムのコレクションはすべての型の基底クラスであるObject型でアイテムを扱っているのためです。 また、文字列以外の型をアイテムとして追加すると、その場合はToString()メソッドによって得られる文字列がリストボックスに表示される文字列となります。

次のコードで様々な型のアイテムを追加し、どのように表示されるかを検証してみます。

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "
#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        With listBoxItems

            ' 選択モード
            .SelectionMode = SelectionMode.MultiExtended

            ' 様々な型のアイテムを追加
            With .Items

                .Add(123456)
                .Add(3.14159265358)
                .Add("文字列")
                .Add(Color.Red)
                .Add(SortOrder.Ascending)
                .Add(New Point(320, 240))
                .Add(New ArrayList())
                .Add(New Pen(Color.Cyan))

            End With

        End With

    End Sub

    Private Sub listBoxItems_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles listBoxItems.SelectedValueChanged

        ' 選択されているアイテム一覧を表示
        Dim o As Object

        listBoxSelectedItems.Items.Clear()

        For Each o In listBoxItems.SelectedItems

            listBoxSelectedItems.Items.Add(o)

        Next

        ' 選択されているアイテムのインデックス一覧を表示
        Dim i As Integer

        listBoxSelectedIndices.Items.Clear()

        For Each i In listBoxItems.SelectedIndices

            listBoxSelectedIndices.Items.Add(i)

        Next

    End Sub

End Class
実行結果

§3 アイテム並べ替えのカスタマイズ

SortedプロパティをTrueに指定すると、表示されている文字のアルファベット順でアイテムが並べ替えられます。 多くの場合はアルファベット順でも問題ないのですが、文字列型以外の型をアイテムとして格納しているとき、アルファベット順では不適切な場合が生じてきます。 そこで、アルファベット順ではない独自の並べ替えを行ってみたいと思います。 そのためにはArrayListのAdapter()メソッドを利用します。

このメソッドは、IListインターフェイスに対してそれをラップするArrayListのラッパーを作成します。 つまり、 IListが実装していないSort()メソッドをArrayListにラップさせることで利用することができるようになります。 Sort()メソッドでは比較子を何も指定しないとデフォルトでアルファベット順に並べ替えられますが、IComparerを実装したクラスのインスタンスを引数に与えると、独自に定義した並べ替えを行わせることができます。

次のコードでは、Point型のアイテムをあらかじめリストボックスに追加しておき、その後でArrayListのラッパーを作成して並べ替えを行います。 並べ替え順を定義するクラスはPointComparerで、このクラスではPoint型変数のYプロパティの値によって並べ替えを行います。 参考までに、SortedプロパティをTrueにしたときの実行結果も添えておきます。

' 独自の並べ替えを定義するクラス
Public Class PointComparer

    Implements IComparer

    ' 座標値による比較
    Public Function Compare(ByVal objX As Object, ByVal objY As Object) As Integer Implements IComparer.Compare

        If objX Is Nothing Then Return 1
        If objY Is Nothing Then Return -1

        Dim ptX As Point = CType(objX, Point)
        Dim ptY As Point = CType(objY, Point)

        If ptX.Y = ptY.Y Then

            ' Yの値が等しいときは、座標は等しいと見なす
            Return 0

        ElseIf ptX.Y > ptY.Y Then

            ' Yの値が大きいときは、座標は大きいと見なす
            Return 1

        Else

            ' それ以外の場合は、座標は小さいと見なす
            Return -1

        End If

    End Function

End Class

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "
#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        With listBoxItems

            ' 選択モード
            .SelectionMode = SelectionMode.MultiExtended

            ' Point型のアイテムを追加
            With .Items

                .Add(New Point(320, 240))
                .Add(New Point(173, 141))
                .Add(New Point(640, 480))
                .Add(New Point(320, 200))
                .Add(New Point(141, 173))
                .Add(New Point(480, 640))
                .Add(New Point(320, 240))
                .Add(New Point(640, 480))
                .Add(New Point(480, 360))
                .Add(New Point(141, 141))

            End With

            ' ArrayListアダプタによる並べ替え
            Dim arr As ArrayList = ArrayList.Adapter(.Items)

            arr.Sort(New PointComparer())

        End With

    End Sub

End Class
実行結果
SortedをTrueにしたとき
SortedをTrueにしたとき
独自に定義した並べ替え
独自に定義した並べ替え

§4 DataSourceプロパティによるアイテムの指定

リストボックスのDataSourceプロパティにIListインターフェイスを実装したオブジェクト(ArrayやDataSetオブジェクト)を指定すると、Itemsプロパティからアイテムを追加しなくても、アイテムを表示させることができます。 つまり、既存の配列やコレクションをアイテムとしてリストボックスに表示できるのです。

DataSourceプロパティにIListインターフェイスを実装したオブジェクトを指定した場合は、DisplayMember及びValueMemberプロパティも指定する必要があります。 DisplayMemberプロパティには、コレクションに含まれるオブジェクトのプロパティのうち、リストボックスに表示するべきプロパティの名前を指定します。 同様に、ValueMemberプロパティにはアイテムを指定する時に用いるプロパティ名を指定します。 ここで、DataSourceプロパティに値を設定した場合は、Itemsプロパティによってアイテムに対する操作を行うことはできません。

次のコードでは、NickNameとFullNameという二つのプロパティを持ったMusumeクラスのオブジェクトを ArrayListオブジェクトに格納し、それをリストボックスのDataSourceプロパティに指定しています。 また、リストボックスの DisplayMemberプロパティにはMusumeクラスのFullNameプロパティ、ValueMemberプロパティにはMusumeクラスの NickNameプロパティを指定しています。

' アイテムとしてリストボックスに追加されるクラス
Public Class Musume

    Private m_NickName As String
    Private m_FullName As String

    Public Sub New(ByVal nickName As String, ByVal fullName As String)

        m_NickName = nickName
        m_FullName = fullName

    End Sub

    Public ReadOnly Property NickName() As String
        Get
            Return m_NickName
        End Get
    End Property

    Public ReadOnly Property FullName() As String
        Get
            Return m_FullName
        End Get
    End Property

    Public Overrides Function ToString() As String

        Return m_FullName + "(" + m_NickName + ")"

    End Function

End Class

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "
#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' 元となるデータ
        Dim arr As New ArrayList()

        With arr

            .Add(New Musume("あいぼん", "加護亜依"))
            .Add(New Musume("チャーミー", "石川梨華"))
            .Add(New Musume("なっち", "安部なつみ"))
            .Add(New Musume("ミキティ", "藤本美貴"))
            .Add(New Musume("こんこん", "紺野あさ美"))

        End With

        With listBoxItems

            ' 選択モード
            .SelectionMode = SelectionMode.MultiExtended

            ' 元となるデータを設定
            .DataSource = arr

            ' リストボックスに表示されるプロパティ
            .DisplayMember = "FullName"

            ' アイテムを指定する時に用いるプロパティ
            .ValueMember = "NickName"

            ' すべての選択を解除
            .ClearSelected()

            ' いくつかのアイテムを、ValueMenberで指定したプロパティにより指定
            .SelectedValue = "チャーミー"
            .SelectedValue = "ミキティ"

            ' この操作はできない
            ' DataSourceに元となるデータを指定しているときは、直接アイテムを操作できない
            '.Items.Add(New Musume("まりっぺ", "矢口真里"))

        End With

    End Sub

End Class
実行結果

この結果を見てわかるとおり、リストボックスにはFullNameプロパティの値で表示され、ソースコードでアイテムを選択する場合はNickNameプロパティの値を用いています。

また、DataSourceプロパティを指定していない他のリストボックスで選択されているアイテムを表示しようとすると次のようになります。 つまり、ToString()メソッドによって得られる文字列をアイテムとして表示します。

実行結果