読者です 読者をやめる 読者になる 読者になる

え〜と、VB.NETでオブジェクトの生成時にクラスを指定する方法の「名前」が判らずどうやってコーディングするねんと思っていましたが、別の調べ物をしてたときに出てきた「ジェネリッククラス」がどうやらそれっぽいので試しに実装してみましたよと。

Public Module ComboItems
    ' コンボボックスの特殊最上段アイテムの種類
    Public Enum emTopItemKind
        ALL     ' すべて
        None    ' なし
    End Enum
End Module

' コードとテキストを保持するコンボボックスアイテムの基底クラス
' ToStringで「Code: Text」形式の文字列を返す
Public Class ComboItemCodeText
    Dim piCode As Integer = 0
    Dim psText As String = ""
    Dim peTopItem As ComboItems.emTopItemKind = emTopItemKind.None
    Dim pbIsTopItem As Boolean = False

    ' 空のアイテムを作成
    Public Sub New()
        Code = 0
        Text = ""
    End Sub

    ' CodeとTextを指定してアイテムを作成
    Public Sub New(ByVal aCode As Integer, ByVal aText As String)
        Code = aCode
        Text = aText
    End Sub

    ' 特殊最上段アイテムを作成
    Public Sub New(ByVal aTopItem As ComboItems.emTopItemKind)
        peTopItem = aTopItem
        pbIsTopItem = True
    End Sub

    ' ComboBoxに表示するテキストを取得
    Public Overrides Function ToString() As String
        If IsTopItem Then
            Return ToTopItemString(Me.TopItem)
        Else
            Return piCode.ToString + ": " + psText
        End If
    End Function

    ' 最上段アイテムの名前を取得(オーバーライド可能)
    Protected Overridable Function ToTopItemString(ByVal aItemKind As emTopItemKind) As String
        Select Case aItemKind
            Case emTopItemKind.ALL
                Return "(すべて)"
            Case emTopItemKind.None
                Return "(なし)"
            Case Else
                Return ""
        End Select
    End Function

    Public Property Code As Integer
        Get
            Return piCode
        End Get
        Set(ByVal value As Integer)
            piCode = value
        End Set
    End Property

    Public Property Text As String
        Get
            Return psText
        End Get
        Set(ByVal value As String)
            psText = value
        End Set
    End Property

    ' 最上段アイテムを作成するにはコンストラクタで指定するしかない(多分その方が安全)
    Public ReadOnly Property TopItem As emTopItemKind
        Get
            Return peTopItem
        End Get
    End Property

    Public ReadOnly Property IsTopItem As Boolean
        Get
            Return pbIsTopItem
        End Get
    End Property
End Class


VB.NET名前空間に定数とか宣言するのってPublic Moduleでいいのかな?
includeやusesの概念がない、スコープがゆるゆりゆるゆるなVB.NETはいやらしいわん。

' コードとテキストに併せてジェネリッククラスのオブジェクトを保持するコンボボックスアイテム
' ToStringで、オブジェクトのToStringを返す
Public Class ComboItemHasObject(Of T)
    Inherits ComboItemCodeText

    Dim poItem As T = Nothing

    Public Sub New(ByVal aItem As T)
        MyBase.New()
        poItem = aItem
    End Sub

    Public Sub New(ByVal aCode As Integer, ByVal aText As String, ByVal aItem As T)
        MyBase.New(aCode, aText)
        poItem = aItem
    End Sub

    ' 特殊最上段アイテムの場合はオブジェクトを格納しない
    Public Sub New(ByVal aTopItem As ComboItems.emTopItemKind)
        MyBase.New(aTopItem)
    End Sub

    Public Overrides Function ToString() As String
        If IsTopItem Then
            Return MyBase.ToString
        Else
            Return poItem.ToString
        End If
    End Function

    Public ReadOnly Property Item As T
        Get
            Return poItem
        End Get
    End Property
End Class

あ、このコードは全くテストしてない*1ので利用は自己責任で。
特に、Tのバインドがいつ行われるか知らないので、コーディングの時点で「oComboItemHasObject.Item.***」としてTに指定したクラスのメンバにアクセス出来るかどうかが定かではありません。出来ないと型キャストの嵐になりそうです。


それでも、格納するクラスごとにComboItemCodeTextを継承したクラスを羅列していた今までのコードよりはすっきりしそうですが。

*1:コンパイラが通るとこまでしか確認してない