Почему мне нужно обновить связанный комбинированный список вручную? - PullRequest
0 голосов
/ 15 ноября 2018

Моя настройка

У меня есть следующие (псевдо) 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
}

У меня есть форма с BindingSource для List(of DepartmentCustomer) и следующими полями:

  • DepartmentCustomer.Information как текстовое поле (чтение-запись)
  • DepartmentCustomer.Customer.Name как (только для чтения) текстовое поле
  • DepartmentCustomer.Customer.City как (чтение-запись) комбинированный список.

CustomerForm

Поле со списком для названия города имеет следующие свойства:

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)

EDIT

Даже код выше не делает то, что я хочу. Например: у меня есть два экземпляра 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, он будет обновлять SelectedItem всякий раз, когда перемещается связанный BindingSource;

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Кажется, есть проблема (ошибка?) С ComboBox привязкой данных к SelectedItem свойству и нулевым (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))
0 голосов
/ 16 ноября 2018

После долгих проб и ошибок я нашел следующее решение:

Принимая во внимание следующий код:

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, а только источник данных должен былреализовать IBindingSource ...

0 голосов
/ 15 ноября 2018

В большинстве случаев, когда элемент управления не обновляется, это проблема, связанная с интерфейсами INotifyPropertyChanged и IBinding List, которые не (правильно) реализованы.- Marco Guignard

Это заставило меня задуматься: я действительно использовал следующее для заполнения DepartmentCustomerBindingSource

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToList

При изменении этого значения на

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.ToBindingList

itработает: - /

Однако как мне это работает, когда для источника данных задается конкретная запись вместо (связующего) списка?

DepartmentCustomerBindingSource.DataSource = DBContext.DepartmentCustomer.Local.First
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...