none
ArrayListのキーと値を重複を除きコンボボックスにセットしたい RRS feed

  • 質問

  • VS2012 Update4でVB.NETを利用しています。


    ComboBoxにDisplayMemberとValuMemberを持たせたい為、ComboBoxのDataSourceをDictionaryEntryでArrayListに追加しています。

                '########### コンボボックスの設定 ###########
                command.CommandText = "SELECT kkkID, kkkName FROM Table A WHERE Delete_Flg = 0  ORDER BY kkkID ASC "
    
                dr = command.ExecuteReader()
    
                Dim lst As New ArrayList()
    
                Do While dr.Read
                    lst.Add(New DictionaryEntry(dr("kkkName"), dr("kkkID")))
                Loop
                cmbK.DataSource = lst
                cmbK.DisplayMember = "Key"
                cmbK.ValueMember = "Value"
                dr.Close()

    ここで、ArrayListに追加する際重複排除したいと思い、ArryList.Containsを利用したいのですが

                Do While dr.Read
                    If lst.Contains(dr("kkkName").ToString() ) = False Then
                        lst.Add(New DictionaryEntry(dr("kkkName"), dr("kkkID")))
                    End If
                Loop

    と記述してみたのですが、重複があるデータも「False」になってしまいます。キーと値がある配列内に対して、Containsをどう記述して良いか分かりません。

    ご教授の程よろしくお願い致します。






    • 編集済み chromeMAO 2014年2月5日 1:26 修正
    2014年2月4日 7:46

回答

  • Dictionary(Of TKey, TValue)はICollection(Of KeyValuePair(Of TKey, TValue))を実装しているので、dictionary.ToList()とすればList(Of KeyValuePair(Of TKey, TValue))を取得できます。

    個人的には、NameとIDの2つのプロパティを持った独自クラスを定義して、それのListを使用することをお勧めしますが…。

    • 回答としてマーク chromeMAO 2014年2月5日 3:13
    2014年2月5日 1:53
  • ToList()に関してはHongliangさんが書かれていますので割愛しますが、そもそもデータをデータベースから読んできているようですので、重複を避けるのであれば、select文にdistinctを付ければ良いだけのような気がします・・・

    >個人的には、NameとIDの2つのプロパティを持った独自クラスを定義して、それのListを使用することをお勧めしますが…。

    同意します。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク chromeMAO 2014年2月5日 3:13
    2014年2月5日 2:16
    モデレータ

すべての返信

  • ArrayListは今はあまり使いませんので、代わりにListなどを使って下さい。
    さて、重複を除くのはLINQで簡単にできます。以下を参考にしてみて下さい。
    ComboBoxにバインドするには、LINQで重複をとった結果に拡張メソッドであるAsDataViewを実行したものを使えば良いかな?

    Distinct OrderBy in LINQ
    http://www.devcurry.com/2010/05/distinct-orderby-in-linq.html

    (追記)
    LINQの結果をComboboxにバインドする例

    Binding to a ComboBox using a DataTable and Linq
    http://msmvps.com/blogs/deborahk/archive/2010/02/27/binding-to-a-combobox-using-a-datatable-and-linq.aspx


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2014年2月4日 8:16
    モデレータ
  • trapemiya様

    返信ありがとうございます。

    ご指摘頂いてからジェネリックコレクションを調べ、Dictionaryを使うことで重複を排除することが出来ました。

    が、Dictionaryに読み込んだキーと値をComboBoxに設定する所でまた躓いています…

    単純にDictionaryをComboBoxのDataSourceにしてみたのですが「Complex DataBinding は IList または IListSource のどちらかをデータソースとして受け入れます。」のエラーが出た為

    ComboBox.DataSource=Dictionary.Values.ToList()

    としました。値は表示されるようになったのですが、キーの設定がわかりません。Dictionary.Keys.ToList()でキー一覧の取得はできるのですが、そもそもせっかくDictionaryで持っているKeyとValueのセットをそのままComboBoxのValueMemberとDisplayMemberに入れる事は出来ないのでしょうか?

    2014年2月5日 1:41
  • Dictionary(Of TKey, TValue)はICollection(Of KeyValuePair(Of TKey, TValue))を実装しているので、dictionary.ToList()とすればList(Of KeyValuePair(Of TKey, TValue))を取得できます。

    個人的には、NameとIDの2つのプロパティを持った独自クラスを定義して、それのListを使用することをお勧めしますが…。

    • 回答としてマーク chromeMAO 2014年2月5日 3:13
    2014年2月5日 1:53
  • ToList()に関してはHongliangさんが書かれていますので割愛しますが、そもそもデータをデータベースから読んできているようですので、重複を避けるのであれば、select文にdistinctを付ければ良いだけのような気がします・・・

    >個人的には、NameとIDの2つのプロパティを持った独自クラスを定義して、それのListを使用することをお勧めしますが…。

    同意します。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク chromeMAO 2014年2月5日 3:13
    2014年2月5日 2:16
    モデレータ
  • Hongliang様、trapemiya様

    ご返信ありがとうございます。

    >個人的には、NameとIDの2つのプロパティを持った独自クラスを定義して、それのListを使用することをお勧めしますが…。

    >>同意します。

    とりあえず教えて頂いた事を調べ希望の動きをすることが出来たのですが、独自クラスを定義して各Listを使う方法をこれから試してみます。

    いつもありがとうございます、本当に助かります。


    • 編集済み chromeMAO 2014年2月5日 6:44
    2014年2月5日 3:13