我并不总是将问题发布到 Stack Overflow,但当我这样做时,我通常会在发布问题之前找到解决方案。 :-) 说真的,我的 BindingSource 出现了奇怪的行为,我找不到合理的解释,我需要你的帮助。
使用 NET 4,通过 EntityFramework 4 读取 SQL 数据库,将结果写入存储在 BindingList 中的 ViewModel 列表,然后通过 BindingSource 绑定(bind)到 DataGridView。在 DataGridView 下,有各种字段,例如复选框、文本字段和组合框,它们绑定(bind)到与 DataGridView 相同的 BindingSource。这样,当您从 DataGridView 中选择一个项目时,所有这些字段都会更新为当前选择的 DataGridView 项目。
假设数据库中有两个表,它们的定义如下:
Table name: Country
-------------------
ID: integer, PK
Name: nvarchar
Table name: City
----------------
ID: integer, PK
CountryID: integer, FK to Country
Name: nvarchar
假设数据库中有一个名为“Citizen”的表,定义如下:
Table name: Citizen
-------------------
ID: integer, PK
CityID: integer, FK to City
Name: nvarchar
... (and other irrelevant fields)
DataGridView 绑定(bind)到 BindingList<CitizenViewModel>
,其中“CitizenViewModel”定义如下:
class CitizenViewModel
{
public int ID { get; set; }
public int CityID { get; set; }
public string Name { get; set; }
public int CountryID { get; set; }
public CitizenViewModel(Citizen c)
{
this.ID = c.ID;
this.CityID = c.CityID;
this.Name = c.Name;
this.CountryID = c.City.CountryID;
}
}
让我们将 DGV 的 BindingSource 命名为 citizenViewModelBindingSource
。
窗体上有两个组合框 cmbCountry
和 cmbCity
,它们分别绑定(bind)到类型为 Country
和 City
的 BindingSources,两个组合框的“DisplayMember”设置为“Name”,“ValueMember”设置为“ID”。 SelectedValue
的cmbCountry
属性绑定(bind)到CountryID
的citizenViewModelBindingSource
属性,SelectedValue
的cmbCity
属性绑定(bind)到同一绑定(bind)源的CityID
属性,所以组合框显示的值会根据在DGV中选择的项目而变化。
我正在处理 CurrentChanged
的 countryBindingSource
事件,它位于 cmbCountry
之后,因此当所选国家/地区发生更改时,cmbCity
会显示该所选国家/地区的城市。
private void countryBindingSource_CurrentChanged(object sender, EventArgs e)
{
// Get the list of Cities that belong to the selected Country
cityBindingSource.DataSource = GetCities(((Country)countryBindingSource.Current).ID);
}
问题如下:假设我的结果集有 5 行,其中 2 行具有相同的 CountryID 但具有不同的 CityID,另外 3 行具有完全不同的 CountryID 和 CityID。当我选择具有相同 CountryID 的两个项目之一,然后选择另一个具有相同 CountryID 的项目时,包含城市的组合框将相应更新。但是,如果我首先选择具有相同 CountryID 的这两个中的一个,然后选择具有不同 CountryID 的其中一个并最终选择具有相同 CountryID 的另一行,绑定(bind)源将神奇地分配与先前选择的行相同的 CityID国家ID。令人困惑?我将举例说明(并省略不相关的字段)。
Results:
1. Name: John Doe; Country: USA; City: Seattle
2. Name: John Smith; Country: Canada; City: Montreal
3. Name: Michael Owen; Country: England; City: Liverpool
4. Name: George Bush; Country: USA; City: Washington
5. Name: Vladimir Putin; Country: Russia; City: Moscow
选择 John Doe,组合框显示美国和西雅图。
选择 George Bush,组合框显示 USA 和 Washington。
选择 John Doe,组合框显示美国和西雅图。
选择 George Bush,组合框显示 USA 和 Washington。所以一切都还好。
选择 Michael Owen,组合框显示 England 和 Liverpool。
选择 John Doe,组合框显示美国和西雅图。
现在看这个。选择 George Bush,组合框显示 USA 和 Seattle(而不是它应该显示的 USA 和 Washington)。绑定(bind)源更改了乔治·布什的 CityID!
我已经写完了这个问题,但我还没有想到解决方案。为什么会发生这种情况以及如何避免这种行为?
编辑
通过解绑 cmbCity
的“SelectedValue”并修改 countryBindingSource_CurrentChanged
函数解决了这个问题:
private void countryBindingSource_CurrentChanged(object sender, EventArgs e)
{
if (citizenViewModelBindingSource.Current != null)
{
cityBindingSource.DataSource = GetCities(((Country)countryBindingSource.Current).ID);
// update the combo box manually
cmbCity.SelectedValue = ((CitizenViewModel)citizenViewModelBindingSource.Current).CityID;
}
}
但这对我来说似乎是一个 hack,如果有人知道为什么会发生这种情况,我将保留这个问题。
最佳答案
通过取消绑定(bind) cmbCity
的“SelectedValue”并手动设置 cmbCity.SelectedValue 解决了这个问题。通过像这样修改 countryBindingSource_CurrentChanged
函数来实现:
private void countryBindingSource_CurrentChanged(object sender, EventArgs e)
{
if (citizenViewModelBindingSource.Current != null)
{
cityBindingSource.DataSource = GetCities(((Country)countryBindingSource.Current).ID);
// update the combo box manually
cmbCity.SelectedValue = ((CitizenViewModel)citizenViewModelBindingSource.Current).CityID;
}
}
“我认为除了摆脱数据绑定(bind)你别无他法,因为在组合框具有数据绑定(bind)时更改其内容会修改绑定(bind)到 Selectedvalue 的属性,不管你喜不喜欢。” ——格特·阿诺德
关于c# - 绑定(bind)源的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16876806/