我并不总是向Stack Overflow发布问题,但是当我这样做时,我通常会在发布问题之前找到解决方案。 :-)说实话,我遇到了BindingSource的奇怪行为,我找不到合理的解释,我需要你的帮助。
使用NET 4,通过EntityFramework 4读取SQL数据库,将结果写入存储在BindingList中的ViewModel列表,然后通过BindingSource绑定到DataGridView。在DataGridView下,有各种字段,例如复选框,文本字段和与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绑定到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
,两者分别绑定到Country
和City
类型的BindingSource,“DisplayMember”设置为“两个组合框的名称“和”ValueMember“设置为”ID“。 SelectedValue
的{{1}}属性绑定到cmbCountry
的{{1}}属性,CountryID
的{{1}}属性绑定到citizenViewModelBindingSource
同一绑定源的属性,因此组合框显示的值会根据在DGV中选择的项目而更改。
我正在处理SelectedValue
cmbCity
后面的CityID
事件,因此当所选国家/地区发生变化时,CurrentChanged
会显示所选国家/地区的城市。
countryBindingSource
问题如下:假设我的结果集有5行,其中2行具有相同的CountryID但不同的CityID,而其他3行具有所有不同的CountryID和CityID。当我选择具有相同CountryID的两个项目之一,然后选择具有相同CountryID的另一个项目时,具有城市的组合框将相应地更新。但是,如果我首先选择具有相同CountryID的这两个中的一个,然后选择具有不同CountryID的那一个并最终选择具有相同CountryID的另一行,则绑定源将神奇地分配与之前选择的具有相同CityID的CityID相同的CityID。 CountryID。混乱?我将用一个例子来解释(并省略不相关的字段)。
结果:
1.姓名:John Doe;国家:美国;城市:西雅图
2.姓名:约翰史密斯;国家:加拿大;城市:蒙特利尔
3.姓名:迈克尔欧文;国家:英格兰;城市:利物浦
名字:乔治布什;国家:美国;城市:华盛顿
5.姓名:弗拉基米尔普京;国家:俄罗斯;城市:莫斯科
选择John Doe,组合框说美国和西雅图 选择乔治布什,组合框说美国和华盛顿 选择John Doe,组合框说美国和西雅图 选择乔治布什,组合框说美国和华盛顿。所以一切都还不错 选择迈克尔欧文,组合框说英格兰和利物浦 选择John Doe,组合框说美国和西雅图 现在看这个。选择乔治布什,组合框说美国和西雅图(不应该是美国和华盛顿)。绑定源改变了乔治布什的CityID!
我已经完成了关于这个问题的写作,但解决方案还没有出现在我的脑海中。为什么会发生这种情况以及如何避免这种行为?
修改
通过解除cmbCountry
的“SelectedValue”绑定并修改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);
}
但这对我来说似乎是一个黑客,如果有人知道为什么会发生这种情况,我会保持这个问题的开放。
答案 0 :(得分:0)
通过解除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;
}
}
“我认为除了数据绑定之外你不能做任何事情,因为在有数据绑定的情况下更改组合框的内容会修改绑定到Selectedvalue的属性,就像它一样。” - 格特阿诺德