2013-06-01 3 views
3

Я не всегда отправляю сообщение об ошибке «Переполнение стека», но когда я это делаю, я обычно нахожу решение, прежде чем закончить публикацию проблемы. :-) Серьезно сейчас, я испытываю странное поведение моего 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; 
     } 
    } 

Но это, кажется, как взломать ко мне, и я буду держать этот вопрос если кто-нибудь узнает, почему это произойдет.

+0

В VB есть значение «Изменено завершено» в поле со списком, когда значение действительно изменилось. Вы пытались это сделать, если выходите на C#? БД обновляется или просто неверна в пользовательском интерфейсе? Возможно, его сбор первого города по имени [S] едет против [W] ашингтон. – Jaxedin

+0

@OwerFlov это был просто пример, факт, что эти два города отсортированы, является совпадением. БД не обновляется, в этом случае нет другого кода, кроме кода, который я опубликовал. Есть событие ListChanged, которое срабатывает с типом ItemChanged, когда я выбираю запись из DGV. –

+1

. Не могли бы вы переместить решение на ответ и пометить его как принятое в свое время? Я думаю, что вы не можете ничего сделать, кроме как уйти от привязки данных, потому что изменение содержимого выпадающего списка, когда оно имеет привязку к данным, изменяет свойство, связанное с Selectedvalue, вроде этого или нет. –

ответ

0

Решил проблему, отделив «SelectedValue» от cmbCity и установив 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 , нравится или нет." - Gert Arnold

Смежные вопросы