リストボックスにおける複数列表示を実現するカスタムコントロール

タグの編集
投稿者 perlman  (社会人) 投稿日時 2010/8/12 14:52:33
おせわになっております。
「Visual Basic中学校」のデータベース講座 第5回データの一覧表示にあります「参考:複数列のコンボボックス」を参考にして、複数列のリストボックスのカスタムコントロールを作成してみました。
しかし、出来上がったカスタムコントロールをフォームに貼り付けると次のようなエラーが表示されて使用することができません。
エラーの示す行を見ると、データを取得するところで誤りが生じているようです。
コンボボックスとリストボックスでは、前者が任意の文字列を入力できるという機能が備わっている点が相違点であり、発生しているエラーはその点が関係しているとは思うのですが、具体的にどのようにしたらよいのかがわかりません。

どのようにコードを修正すればよいのか、何方様かご教示おねがいします。

エラー表示のメッセージ
--------------------------------------------------------------------------
コントロール WindowsApplication1.ListBoxEx がデザイナーでハンドルされていない例外をスローして、無効になりました。

例外:
‘0’のInvalidArgument=Valueは‘index’に対して有効ではありません。
パラメータ名:index

スタック トレース:
 場所 WindowsApplication1.ListBoxEx.OnDrawItem(DrawItemEventArgs e) 場所 d:\mydoc\visual studio2010\Projects\list1\list1\Class1.vb:行 26
--------------------------------------------------------------------------

関係しているコード

' ▼データの内容を取得
        Dim Row As DataRowView
        Dim ItemString1 As String
        Dim ItemString2 As String

        Row = DirectCast(Me.Items(e.Index), DataRowView)
        ItemString1 = Row(ListMember1)
        ItemString2 = Row(ListMember2)

投稿者 perlman  (社会人) 投稿日時 2010/8/12 15:15:23
追記です。

作成したカスタムコントロール「ListBoxEx」のクラスのコードを、プロジェクト内に置いて動かす限りは期待した動作(表示)をしてくれたので、問題ないと考えていたのですが、ツールボックスに追加されたカスタムコントロール「ListBoxEx」をフォームに貼り付けたらエラーしたというわけです。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/8/12 16:55:45
>         Row = DirectCast(Me.Items(e.Index), DataRowView)
e.Index の値が、Me.Items に指定可能な範囲を超えていませんか?

-1 になっているとか、Me.Items.Count 以上の値になっているとか。
投稿者 perlman  (社会人) 投稿日時 2010/8/12 19:50:19
ご回答ありがとうございます。

作成した「ListBoxEx」は、Visual Basic 中学校の管理人さんが作成された「複数列のコンボボックス(ComboBoxEx)」をほとんどそのまま利用したのですが、そちらのほうは何のエラーも発生していないのです。
ご指摘のあったところは、初期値の指定は無いのでなぜエラーするのかわからないのです。(泣;)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/8/12 20:36:03
> 初期値の指定は無いのでなぜエラーするのかわからないのです。(泣;)
データが無いから、では?

先ほどの回答でも触れていますが、エラーが発生した時に、
e.Index にどのような値が渡されているかを調査してみましょう。
Try
    'エラーになるかも知れない行 
    Row = DirectCast(Me.Items(e.Index), DataRowView)
Catch ex As Exception
    'エラー発生時に内容を表示 
    MsgBox(String.Format("e.Index={0}, Me.Items.Count={1}:" _
        & vbCrLf & "{2}", e.Index, Me.Items.Count, ex.Message))
End Try



で、エラーメッセージを見る限りでは、
>> ‘0’のInvalidArgument=Valueは‘index’に対して有効ではありません。
と書かれているようなので、e.Index が 0 であるという事が分かりますよね。
リスト内にデータが一個も無い場合には、Me.Items(0) にアクセスする事はできません。

そして、もしもこれが原因なのであれば、Me.Items(e.Index)する前に、
e.Index や Me.Items.Count の件数をチェックするコードを書けば、
Me.Items に範囲外の値を渡さないようにできますよね。

> そちらのほうは何のエラーも発生していないのです。
コンボボックスの描画は、ドロップダウン時にしか発生しないからです。
データが未登録なら猶の事。

とはいえ ComboBoxEx の方にしても、DropDownStyle を DropDown にすれば、
入力部(テキストボックス)も描画対象になるので、今回の現象と同様の問題が
起きるはずです。これも上記同様、e.Index 等の値を If ~ Then で判定するなどして
Me.Items(異常値) が行われないように回避しましょう。