Как я могу связать ассоциацию Entity Framework с ComboBox? - PullRequest
7 голосов
/ 09 августа 2011

Я работаю над внутренней программой отслеживания программного обеспечения, и каждой ревизии программы назначается ведущий программист из базы данных сотрудников.Моя простая модель выглядит так:

Entity Framework model

Изначально у меня был объект RevisionBindingSource, который был привязан к моей коллекции Revisions:

Dim container as new EntityContainer
revisionBindingSource.DataSource = container.Revisions
...
dgRevisions.DataSource = revisionBindingSource
dgRevisions.DataMemeber = ""

Это сработало хорошо, и я смог привязать к различным требуемым свойствам, таким как название приложения:

lblAppTitle.DataBindings.Add("Text",revisionBindingSource,"Application.Title")

Однако мне теперь нужен ComboBox, элементы которого привязаны к списку сотрудников, ивыбранное значение которого привязано к ведущему программисту текущей ревизии.Я попытался создать новый employeeBindingSource, но понял, что у меня нет элемента привязки для Value:

employeeBindingSource.DataSource = container.Employees
...
cboLead.DataSource = employeeBindingSource
cboLead.DisplayMember = "Name.Display" 'Name is a complex type'
cboLead.ValueMember = '??

Поэтому я переписал некоторые из моих привязок, чтобы иметь только одну bindingSource:

bindingSource.DataSource = container
...
dgRevisions.DataSource = bindingSource
dgRevisions.DataMemeber = "Revisions"
...
cboLead.DataSource = bindingSource
cboLead.DisplayMember = "Employees.Name.Display"
cboLead.ValueMember = "Employees"
...
lblAppTitle.DataBindings.Add("Text",bindingSource,"Revisions.Application.Title")

Это все еще даже не заполняет ComboBox чем-либо.

Какой шаблон мне лучше использовать - два разных источника привязки или один?Что я делаю неправильно, связывая мой ComboBox?И как только заполнится мой ComboBox, как я могу связать текущее значение с ведущим программистом ревизии?

Извините за длинный вопрос, и спасибо.

1 Ответ

3 голосов
/ 31 октября 2011

Нет ничего плохого в том, что в вашей форме есть более одного обязательного источника.На самом деле, «связывание» источников привязки, как вы предлагаете выше, может быть удобной стратегией.

Однако в этой ситуации существует недостающая ссылка, которую вам нужно будет заполнить для поддержки связывания .Valueсвойство фактического объекта EF: вам потребуется создать отдельный класс для привязки. Этот метод также очень полезен при привязке к перечислениям.

Этот метод очень распространен, когда ваш EFмодель данных не совсем соответствует тому, как вы хотите, чтобы ваш пользовательский интерфейс работал.Для WPF (не WinForms, как в этом примере), это часто упоминается как часть ViewModel.После того, как вы сделаете это несколько раз, это станет второй натурой.

Вот пример реализации класса, который вам нужно будет создать:

public class EmployeeBindingObject
{
    public Employee Employee { get; private set; }
    public string EmployeeName 
    { 
        get { return this.Employee.Name; }
    }

    private EmployeeBindingObject(Employee employee)
    {
        this.Employee = employee;
    }

    /// <summary>
    /// Gets a binding list for a specified list of Employees.
    /// </summary>
    /// <param name="types"></param>
    /// <returns></returns>
    public static IBindingList GetBindingList(IEnumerable<Employee> employees)
    {
        BindingList<EmployeeBindingObject> result = new BindingList<EmployeeBindingObject>();

        foreach (var ee in employees)
        {
            result.Add(new EmployeeBindingObject(ee));
        }

        return result;
    }
}

Как только вы создадите этот класс, выдолжен скомпилировать, а затем создать источник данных (Данные -> Добавить новый источник данных ...) для EmployeeBindingObject.

  1. Установите ValueMember на Employee
  2. Установите DisplayMember на EmployeeName
  3. Установите свойство SelectedValue для вашего другого BindingSource's Employee property.
  4. Затем в вашем коде вам нужно инициализировать объект привязки BindingSource следующим образом:

     employeeBindingObjectBindingSource.DataSource = 
         EmployeeBindingObject.GetBindingList(container.Employees)
    
...