2016-06-28 7 views
1

長い間、私はコンボボックスの問題を解決しようとしていました(試したテストとフォーラムの数を考えると頭がおかしくなります)。私は、コンボボックスがソースに「バインド」された後、コンボボックスと同期されることを知っています(すべての変更はコンボボックスに表示されます)。コンボボックスに使用されているbindingSourceを更新する

Public Class Form1 
    Dim a As New BindingSource, b As New Hashtable 


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     ComboBox1.DataSource = a 
     ComboBox2.DataSource = a 


     b.Add(1, "a") 
     b.Add(2, "b") 


     a.DataSource = b 
     a.DataMember = "Value" 



     '' Tried this when a.DataMember is commented .Otherwise it gives error 
     ''ComboBox1.DisplayMember = "Value" 
     ''ComboBox1.ValueMember = "Key" 
     ''ComboBox2.DisplayMember = "Value" 
     ''ComboBox2.ValueMember = "Key" 
    End Sub 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     b.Add(3, "c") ''Nothing new in the combobox 
     ''a.ResetBindings(False) 
    End Sub 
End Class 


これは、それがどのように見えるかです::
はここに私の簡単なテストコードです

enter image description here


私は、コンボボックスのDisplayMemberとValueMemberでプロパティをデコメントすると、この何が起こるか(Button1を押した後):

enter image description here
Countプロパティには2つの項目があると書かれていますが、DataSourceには3があると言われています。なぜなら、新しく追加された項目は表示されないからです(Button1を押すと、それがBindingSourceに格納されているにもかかわらず追加されました)。
問題はどこですか?

注:私はMSDNに多分何か役に立つが見つかりましたが、非常に(私はこのページによると、コードを更新)働いていません。

答えて

2

I know that after a combobox has been "binded" to a source it will be synchronised with it(every change will appear in combobox).

問題は、あなたの理解は完全に真実ではないということです。コントロールに自動的に表示される内容の変更には、特別なコレクションを使用する必要があります。コレクションの内容がタイプ(クラス)である場合、プロパティの1つに対する変更は、別のステップなしで自動的には表示されません。

これを克服するためのハム・こぶしの方法は、DataSourceを「リセット」することです:

cbox.DataSource = Nothing 
ht.Add(0, "Zulu") 
cbox.DataSource = New BindingSource(ht, Nothing) 
cbox.DisplayMember = "Value" 
cbox.ValueMember = "Key" 

これはBindingSourceを再構築(またはこの場合は新しいものを構築する)ので、新しいエントリを「見る」ことができます。 Display-ValueMemberの値が失われているため、それらの値をリセットする必要があります。 「リセット中」でもListBoxのような問題が発生する可能性があります。以前の選択が失われるためです。内の各エントリを保持しているタイプ

cboBS.Add(New DictionaryEntry(0, "Zulu")) 
  • はコンボ
  • DictionaryEntryためBindingSourceです:

    は、基になるコレクションに応じて、反対をしBindingSourceに組み込まれた方法がありa HashTable

今、新しいエントリが表示され、BindingSourceにありますが、それは基盤のHashTableにありません。新しいアイテムはList<T>のようなものに追加されます(HashSet<T>HashTableよりも良い選択です)。


ほとんどのコレクションの問題は、追加または削除されたときに、アイテム彼らはシグナル伝達しないということです。ほとんどのコレクションはこのようなもので、BindingSourceで解決できません。

あなたの最善の策はBindingList(Of T)です。 (これは、HashTableの場合、値が追加されているかどうかを確認するだけですが、例外を避けるためにはHashTableとする必要があります)。もう1つはうまくいくかもしれませんが、奇妙に見えるかもしれません。 DataTable

Private BList As BindingList(Of NameValuePair) 
... 
BList = New BindingList(Of NameValuePair) 
BList.Add(New NameValuePair("Alpha", 1)) 
BList.Add(New NameValuePair("Delta", 4)) 
BList.Add(New NameValuePair("Gamma", 3)) 
BList.Add(New NameValuePair("Beta", 2)) 
cbox.DataSource = BList 
cbox.DisplayMember = "Name" 
cbox.ValueMember = "Value" 

BindingSourceはもう必要ありません。 NameValuePairは、Valueを '名前'に関連付ける簡単なユーティリティクラスfound hereです。 KeyValuePair(Of TK, TV)も使用できます。

リストにam項目を追加するには、余分な手順が必要でなく、再バインディングも必要ありません。自動的に表示されます。あなたは、リスト内の項目のプロパティを変更する場合は、:

myPersonList(0).Name = "Ziggy" 

を基本となるクラスがINotifyPropertyChangeを実装していない限り...これらの変更は表示されませます。

上記のリンクは別の質問に近づいています:Assigning a value to ComboBox Itemsまた役に立つかもしれません。

blog entry listed in the commentもかなり良いです。また、Whys and Whereforesにいくつかの情報が含まれている他のコレクションやユースケースについても説明します。

+0

https://blogs.msdn.microsoft.com/dchandnani/2005/03/15/bindingsource-a-closer-look/のブログでも同様の解決策を導いてくれました。あなたのものは私が書いたものよりもはるかに深いです。 +1 – topshot

関連する問題