【问题标题】:Why do I need to update a bound combobox manually?为什么我需要手动更新绑定的组合框?
【发布时间】:2019-04-18 07:18:17
【问题描述】:

我的设置

我有以下(伪)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
}

我有一个带有 List(of DepartmentCustomer) 的 BindingSource 和以下字段的表单:

  • DepartmentCustomer.Information 作为(读写)文本框
  • 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出现时,Combobox不同步;它有时会更新为正确的值,但是当进一步浏览 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 实例,一个带有 Contact.City,第二个没有 Contact.City。当表单第一次打开时,它会显示城市;当我导航到第二条记录时,组合框变为空,但是当我回到第一个组合框时,它保持为空;更令人惊讶的是,第一条记录已经更新为 Contact.City = Nothing :'(

编辑 2:我自己不喜欢的解决方案

我已从组合框 (ComboBoxCity.DataBindings.Add(New Binding("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 未正确更新...

我的问题

为什么我必须手动执行此操作;我错过了什么吗?我认为通过设置 DataBinding,只要导航绑定的 BindingSource,它就会更新 SelectedItem;

【问题讨论】:

  • 大多数情况下,控件不更新是与接口 INotifyPropertyChanged 和 IBinding​List 未(正确)实现相关的问题。
  • @MarcoGuignard 谢谢!!!请参阅下面的答案(以及我的附加问题)

标签: vb.net winforms entity-framework-6


【解决方案1】:

ComboBox 数据绑定到 SelectedItem 属性和 null (Nothing) 源值似乎存在问题(错误?)。

从另一端绑定到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))

【讨论】:

  • 真的吗?那看起来很疯狂。也许有任何参考资料?
  • 参考?你一定是在开玩笑 :) 反复试验。
【解决方案2】:

大多数情况下,控件不更新是与接口 INotifyPropertyChanged 和 IBinding​List 未(正确)实现相关的问题。 ——马可·吉纳德

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

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToList

将其更改为

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToBindingList

它有效:-/

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

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.First

【讨论】:

  • 将 INotifyPropertyChanged 的​​实现添加到 DepartmentCustomer 类 docs.microsoft.com/en-us/dotnet/api/… 顺便说一句,您最好使用 ForeignKey 属性来做组合框的选定值之间的链接
  • @MarcoGuignard 我不知道为什么以及如何这样做。每个想要使用 Combobox 来更新 EF POCO 的人都必须实现这个吗?
  • 在组合框上,将数据源设置为城市集合(如果不更新城市列表,列表就足够了),将 DisplayMember 设置为 Name,将 ValueMember 设置为 ID。然后在组合框的 SelectedValue 和包含客户的 BindingSource 的 CityID 属性之间设置绑定。
【解决方案3】:

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

考虑以下代码:

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)必须是 BindingList,而只有 Datasource 必须实现 IBindingSource...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 2012-06-12
    相关资源
    最近更新 更多