Я не всегда отправляю сообщение об ошибке «Переполнение стека», но когда я это делаю, я обычно нахожу решение, прежде чем закончить публикацию проблемы. :-) Серьезно сейчас, я испытываю странное поведение моего BindingSource, я не могу найти для этого логического объяснения, и мне нужна ваша помощь.Неожиданное поведение источника привязки
Использование NET 4, чтение базы данных SQL через EntityFramework 4, запись результатов в список ViewModels, которые хранятся в BindingList, который затем привязан к DataGridView через BindingSource. В DataGridView существуют различные поля, такие как флажки, текстовые поля и комбинированные поля, привязанные к тому же BindingSource, что и DataGridView. Таким образом, при выборе элемента из DataGridView все эти поля обновляются с помощью выбранного элемента DataGridView.
Допустим, есть две таблицы в базе данных, которые определяются следующим образом:
Table name: Country
-------------------
ID: integer, PK
Name: nvarchar
Table name: City
----------------
ID: integer, PK
CountryID: integer, FK to Country
Name: nvarchar
Давайте также сказать, что есть таблица в базе данных под названием «Гражданин» определяется следующим образом:
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 citizenViewModelBindingSource
.
Есть два комбо коробки на форме, cmbCountry
и cmbCity
, как связанные с BindingSources из Country
и City
типа соответственно, с «DisplayMember» установлен в «Имя» и «ValueMember» установлен на «ID» для обоих полей со списком , SelectedValue
свойства cmbCountry
связанно с CountryID
свойства citizenViewModelBindingSource
и SelectedValue
свойства cmbCity
привязано к свойству 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 имеют все разные CountryIDs и CityIDs. Когда я выбираю один из двух элементов с тем же идентификатором страны, а затем выбираю другой с тем же идентификатором страны, соответственно будет обновляться поле со списком с городами. Однако, если я сначала выберу один из этих двух с тем же идентификатором страны, а затем выберите один из них с другим идентификатором страны и в конечном итоге выберите другую строку с тем же идентификатором страны, источник привязки будет магически назначать тот же самый Городский идентификатор, что и ранее выбранная строка с тем же CountryId. Смешение? Я объясню пример (и пропущу нерелевантные поля).
Результаты:
1. Наименование: John Doe; Страна: США; Город: Сиэтл
2. Имя: John Smith; Страна: Канада; Город: Монреаль
3. Имя: Майкл Оуэн; Страна: Англия; Город: Ливерпуль
4. Имя: Джордж Буш; Страна: США; Город: Вашингтон
5.Имя: Владимир Путин; Страна: Россия; Город: Москва
Выбрать John Doe, комбо-поля США и Сиэтл.
Выберите «Джордж Буш», комбо-боксы говорят, что США и Вашингтон.
Выберите John Doe, комбо-боксы говорят, что США и Сиэтл.
Выберите «Джордж Буш», комбо-боксы говорят, что США и Вашингтон. Так что все по-прежнему хорошо.
Выберите Майкл Оуэн, комбо-боксы говорят, что Англия и Ливерпуль.
Выберите John Doe, комбо-боксы говорят, что США и Сиэтл.
Теперь смотрите это. Выберите Джорджа Буша, комбо-боксы говорят, что США и Сиэтл (а не США и Вашингтон, как следует). Источник привязки изменил CityID Джорджа Буша!
Я закончил писать о проблеме, но решение не пришло мне в голову. Почему это происходит и как избежать такого поведения?
EDIT
решил проблему отменяя в «SelectedValue» из cmbCity
и модификации 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;
}
}
Но это, кажется, как взломать ко мне, и я буду держать этот вопрос если кто-нибудь узнает, почему это произойдет.
В VB есть значение «Изменено завершено» в поле со списком, когда значение действительно изменилось. Вы пытались это сделать, если выходите на C#? БД обновляется или просто неверна в пользовательском интерфейсе? Возможно, его сбор первого города по имени [S] едет против [W] ашингтон. – Jaxedin
@OwerFlov это был просто пример, факт, что эти два города отсортированы, является совпадением. БД не обновляется, в этом случае нет другого кода, кроме кода, который я опубликовал. Есть событие ListChanged, которое срабатывает с типом ItemChanged, когда я выбираю запись из DGV. –
. Не могли бы вы переместить решение на ответ и пометить его как принятое в свое время? Я думаю, что вы не можете ничего сделать, кроме как уйти от привязки данных, потому что изменение содержимого выпадающего списка, когда оно имеет привязку к данным, изменяет свойство, связанное с Selectedvalue, вроде этого или нет. –