【问题标题】:Update bindingSource used for combobox更新用于组合框的 bindingSource
【发布时间】:2016-06-28 21:02:20
【问题描述】:

很长一段时间以来,我一直在尝试解决组合框的问题(当我想到我尝试过多少测试和论坛时,这让我很头疼)。我知道在组合框“绑定”到源之后,它将与它同步(每个更改都将出现在组合框中)。
这是我的简单测试代码:

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


看起来是这样的:


当我取消注释组合框的 DisplayMember 和 ValueMember 属性时,会发生这种情况(在按下 Button1 之后):


如您所见,count 属性说有 2 个项目,但 DataSource 说有 3 个。我认为这就是为什么没有出现新添加的项目(当我按下 Button1 时,尽管事实上它存储在 BindingSource 中)。
问题出在哪里?

注意:我在MSDN 上发现了一些可能有用的东西,但它不是很有效(我根据此页面更新了代码)。

【问题讨论】:

    标签: .net vb.net binding


    【解决方案1】:

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

    问题是你的理解并不完全正确。您需要使用特殊的集合来更改内容以自动显示在控件中。如果集合的内容是类型(类),则对其中一个属性的更改不会自动显示而无需其他步骤。

    解决这个问题的笨拙方法是“重置”DataSource

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

    这将重建BindingSource(或在这种情况下构建一个新的),以便它可以“看到”新条目。 Display-ValueMember 值丢失,因此您必须重置它们。 “重置”也可能导致ListBox 之类的问题,因为之前的任何选择都将丢失。

    BindingSource 中内置了一种方法,它根据底层集合执行相反的操作:

    cboBS.Add(New DictionaryEntry(0, "Zulu"))
    
    • cboBS 是 Combo 的 BindingSource
    • DictionaryEntry 是在 HashTable 中保存每个条目的类型。

    现在,新条目显示在 BindingSource 中,但不在您的底层 HashTable 中。新项目将添加到 List<T> 之类的内容中(HashSet<T> 将是比 HashTable 更好的选择)。


    大多数集合的问题是它们没有发出何时添加或删除项目的信号。大多数集合都是这样,BindingSource 无法解决。

    您最好的选择可能是使用BindingList(Of T)。 (如果HashTable,这不会强制执行唯一键约束,只需检查是否已添加该值-无论如何您都需要使用HashTable 来避免异常。)另一件可行的事情-但可能看起来奇数 - 是 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"
    

    您不再需要BindingSourceNameValuePair 是一个简单的实用程序类 found here,用于将 Value 与“名称”相关联。您也可以使用KeyValuePair(Of TK, TV)

    将 am 项添加到列表中,不需要额外的步骤,也不需要重新绑定。它会自动显示。但是,如果您更改列表中某个项目的属性:

    myPersonList(0).Name = "Ziggy"
    

    ...除非底层类实现INotifyPropertyChange,否则这些更改将不会显示出来。

    上面的链接以不同的方式解决了这个问题:Assigning a value to ComboBox Items,也可能会有所帮助。

    blog entry listed in the comment 也不错。它还涵盖了一些关于其他集合和用例的信息,并在为什么和原因中提供了一些信息。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    相关资源
    最近更新 更多