1

データベースからリストをロードする単純なサブルーチンがあります。リストタイプを共通の抽象基本クラスListControlとして定義することで、同じコードを使用してListBoxとComboBoxをロードできるようにしたいのですが、VB.NETが公開しないことを除いて、できない理由はわかりません。 ListControlのItemsコレクションを/implement/whatever。これはASP.NETには当てはまらないことに不満を持って注意します。現時点では、Itemsコレクションを持つタイプにキャストするために、渡したリストコントロールのタイプを確認する必要があるため、コードは醜いです。(私のコードは他の多くの理由でも醜いかもしれませんが、それは私にとって美しいです)。テストやナンセンスのキャストを回避するためにコードを書き直す方法はありますか?(私はそれをいくらか取り除いたので、残っているのは問題があるところだけです)。

Sub loadList(ByVal db As SqlDatabase, ByVal strCommandText As String, lstHost As ListControl, Optional bClearList As Boolean = True, Optional bIsListBox As Boolean = True)
    If bClearList Then
        If bIsListBox Then
            CType(lstHost, ListBox).Items.Clear()
        Else
            CType(lstHost, ComboBox).Items.Clear()
        End If
    End If
    Dim dt As DataTable = db.ExecuteDataSet(db.GetSqlStringCommand(strCommandText)).Tables(0)
    For i = 0 To dt.Rows.Count - 1
        If bIsListBox Then
            CType(lstHost, ListBox).Items.Add(dt.Rows(i)(0).ToString)
        Else
            CType(lstHost, ComboBox).Items.Add(dt.Rows(i)(0).ToString)
        End If
    Next
End Sub
4

1 に答える 1

1

これは、winforms では ListBox オブジェクト コレクションが ComboBox オブジェクト コレクションと異なるためです。これを整理するために私が考えることができる最も簡単な方法は、ヘルパークラスを次のようにすることです

Public Class ListHelper
    Public Shared Sub Clear(ByRef lst As ListControl)
        If TypeOf lst Is ListBox Then
            CType(lst, ListBox).Items.Clear()
        Else
            CType(lst, ComboBox).Items.Clear()
        End If
    End Sub

    Public Shared Sub Add(ByRef lst As ListControl, ByVal itm As Object)
        If TypeOf lst Is ListBox Then
            CType(lst, ListBox).Items.Add(itm)
        Else
            CType(lst, ComboBox).Items.Add(itm)
        End If
    End Sub
End Class

次に、コードで次のことができます。

Sub loadList(ByVal db As SqlDatabase, ByVal strCommandText As String, _
  ByVal lstHost As ListControl, Optional ByVal bClearList As Boolean = True)
    If bClearList Then
        ListHelper.Clear(lstHost)
    End If
    Dim dt As DataTable = _
      db.ExecuteDataSet(db.GetSqlStringCommand(strCommandText)).Tables(0)
    For i = 0 To dt.Rows.Count - 1
        ListHelper.Add(lstHost, dt.Rows(i)(0).ToString)
    Next
End Sub

編集 :

これを行う別の(おそらくより良い)方法は、拡張メソッドを使用することです(新しいモジュールを追加して):

Imports System.Runtime.CompilerServices
Module ListExtensions
    <Extension()> _
    Public Sub AddToItems(ByRef lc As ListControl, ByVal itm As Object)
        If TypeOf lc Is ListBox Then
            CType(lc, ListBox).Items.Add(itm)
        ElseIf TypeOf lc is ComboBox then
            CType(lc, ComboBox).Items.Add(itm)
        Else
            'handle abuse
        End If
    End Sub

    <Extension()> _
    Public Sub ClearItems(ByRef lc As ListControl)
        If TypeOf lc Is ListBox Then
            CType(lc, ListBox).Items.Clear()
        ElseIf TypeOf lc is ComboBox Then
            CType(lc, ComboBox).Items.Clear()
        Else
            'handle abuse
        End If
    End Sub
End Module

これは、コードでさらに少しきれいになります:

Sub loadList(ByVal db As SqlDatabase, ByVal strCommandText As String, _
  ByVal lstHost As ListControl, Optional ByVal bClearList As Boolean = True)
    If bClearList Then
        lstHost.ClearItems()
    End If
    Dim dt As DataTable = _
      db.ExecuteDataSet(db.GetSqlStringCommand(strCommandText)).Tables(0)
    For i = 0 To dt.Rows.Count - 1
        lstHost.AddToItems(dt.Rows(i)(0).ToString)
    Next
End Sub

ここでは、インスタンス メソッドのあいまいさを避けるために、これらClearItemsを呼び出しました。ListControl にはor自体AddToItemsはありませんが、明示的にするために、拡張機能に固有の命名法を使用するのがおそらく最善です。.Clear().Add()

于 2012-04-11T16:26:39.327 に答える