Vb.net 为什么我需要手动更新绑定的组合框?

Vb.net 为什么我需要手动更新绑定的组合框?,vb.net,winforms,entity-framework-6,Vb.net,Winforms,Entity Framework 6,我的设置 我有以下(伪)EF类: class Department { int ID, string Name } class DepartmentCustomer { int ID, int CustomerID, Customer Customer, string Information, int DepartmentID, Department Department } Class Customer { int I

我的设置

我有以下(伪)EF类:

class Department {
    int ID,
    string Name
}

class DepartmentCustomer {
    int ID,
    int CustomerID,
    Customer Customer,
    string Information,
    int DepartmentID,
    Department Department
}

Class Customer {
    int ID,
    string Name,
    int? CityID,
    City City
}

Class City{
    int ID,
    string Name,
    string PostalCode
}
我有一个带有BindingSource的表单,用于
列表(部门客户)
和以下字段:

  • 部门客户信息
    作为(读写)文本框
  • DepartmentCustomer.Customer.Name
    作为(只读)文本框
  • DepartmentCustomer.Customer.City
    作为(读写)组合框

城市名称的组合框具有以下属性:

ComboBoxCity.DataSource = ListOfCities  ' = List(Of City)
ComboBoxCity.ValueMember = "Id"
ComboBoxCity.DisplayMember = "Name"
ComboBoxCity.DataBindings.Add(New Binding("SelectedItem", DepartmentCustomerBindingSource, "Customer.City", True, DataSourceUpdateMode.OnPropertyChanged))
我的问题

当发生
DepartmentCustomerBindingSource.CurrentItemChanged
时,组合框不同步;它有时会更新为正确的值,但在通过BindingSource进一步导航时,它会保持上一个项目处于选中状态

因此,我必须执行以下操作来手动更新组合框

Private Sub DepartmentCustomerBindingSource_CurrentItemChanged(sender As Object, e As EventArgs) Handles DepartmentCustomerBindingSource.CurrentItemChanged
    If DepartmentCustomerBindingSource.Current.Contact.City Is Nothing then
        ComboBoxCity.SelectedIndex = -1
    Else
        ComboBoxCity.SelectedItem = DepartmentCustomerBindingSource.Current.Contact.City
    End if
End Sub
(为了简单起见,我在上面的代码中加入了强制转换。此外,这些示例类在IRL中可能没有意义)

编辑

即使上面的代码也不能满足我的要求。 例如:我有两个DepartmentCustomer实例,一个有联系人.City,第二个没有联系人.City。当表单第一次打开时,它显示城市;当我导航到第二条记录时,组合框变为空,但当我返回到第一条组合框时,它保持为空;更令人惊讶的是,第一条记录已更新为Contact.City=Nothing:'(

编辑2:我自己的非首选解决方案

我已经从组合框中删除了数据绑定(
ComboBoxCity.DataBindings.Add(新绑定(“SelectedItem”,DepartmentCustomerBindingSource,“Customer.City”,True,DataSourceUpdateMode.OnPropertyChanged))
)并添加了以下子绑定

Private Sub ComboBoxCity_SelectedValueChanged(sender As Object, e As EventArgs) Handles ComboBoxCity.SelectedValueChanged
    DepartmentCustomerBindingSource.Current.Contact.City = ComboBoxCity.SelectedItem
End Sub
这是可行的,但由于我的表单中有很多这样的组合框,我认为必须有一种“自动”方式来同步双向绑定的组合框

编辑3:我认输了

即使是我上面的“解决方案”也没有按预期工作;在使用上述代码时,实例的Contact.City没有正确更新

我的问题

为什么我必须手动执行此操作;我是否遗漏了什么?我认为通过设置数据绑定,它将在导航绑定的BindingSource时更新SelectedItem


大多数情况下,当控件不更新时,这是一个与接口INotifyPropertyChanged和IBinding相关的问题​列表未(正确)执行–Marco Guignard

这让我想到:我确实在使用下面的内容填充DepartmentCustomerBindingSource

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToList
当更改为

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToBindingList
它的工作原理是:-/

但是,当将数据源设置为特定记录而不是(绑定)列表时,如何使其工作


SelectedItem
属性和null(
Nothing
)源值绑定的
ComboBox
数据似乎存在问题(bug?)

从另一端绑定到
SelectedValue
没有此类问题。因此,解决方案/解决方法是绑定到
SelectedItem
以更新数据源,绑定到
SelectedValue
以更新控件:

ComboBoxCity.DataBindings.Add(New Binding("SelectedItem", DepartmentCustomerBindingSource, "Customer.City", True, DataSourceUpdateMode.OnPropertyChanged))    
ComboBoxCity.DataBindings.Add(New Binding("SelectedValue", DepartmentCustomerBindingSource, "Customer.City.ID", True, DataSourceUpdateMode.Never))

经过反复试验,我找到了以下解决方案:

考虑到以下准则:

ComboBoxCity.DataSource = ListOfCities  ' = List(Of City)
ComboBoxCity.ValueMember = "Id"
ComboBoxCity.DisplayMember = "Name"
ComboBoxCity.DataBindings.Add(New Binding("SelectedItem", DepartmentCustomerBindingSource, "Customer.City", True, DataSourceUpdateMode.OnPropertyChanged))
让我开始的是将
ComboBoxCity.DataSource
设置为实现IBindingList的类型,如下所示:

DBContext.Cities.Load
CitiesBindingSource.DataSource = DBContext.Cities.Local.ToBindingList
ComboBoxCity.DataSource = CitiesBindingSource

因此,绑定数据(在本例中为
DepartmentCustomerBindingSource
)不必是绑定列表,而只有数据源必须实现IBindingSource…

大多数情况下,当控件不更新时,这是与INotifyPropertyChanged和IBinding接口相关的问题​列表未(正确)执行。@MarcoGuignard谢谢!!!看到我下面的答案(以及我的附加问题)真的吗?那看起来很疯狂。可能有参考资料吗?参考资料?你一定是在开玩笑:)尝试和错误。将INotifyPropertyChanged的实现添加到DepartmentCustomer类中,方法是最好使用ForeignKey属性在组合的选定值之间进行链接box@MarcoGuignard我不知道为什么以及如何去做。每个想使用组合框更新EF POCO的人都必须实现这一点吗?在组合框上,将数据源设置为城市集合(如果不更新城市列表,列表就足够了),将DisplayMember设置为Name,ValueMember设置为ID。然后在组合框的SelectedValue和包含客户的BindingSource的CityID属性之间设置绑定。
DBContext.Cities.Load
CitiesBindingSource.DataSource = DBContext.Cities.Local.ToBindingList
ComboBoxCity.DataSource = CitiesBindingSource