Привязка данных столбца комбинированного списка к сетке данных для каждой строки (не для всего столбца)

Есть несколько сообщений об этом, но после нескольких часов поиска я все еще не могу найти то, что мне нужно.

Ответ в следующем посте почти дает мне то, что я хочу: Combobox для внешнего ключа в DataGridView

Вопрос 1:

Если исходить из того примера, когда у продукта много лицензий, все сопоставления моей базы данных - это отношения многие-к-одному, что означает, что мой класс License содержит ссылку на класс Product. Класс License не имеет свойства для ProductId, поскольку его можно получить с помощью ссылки на Product. Я не хочу портить класс License и ссылкой на Product, и на свойство ProductId, чтобы упростить привязку в пользовательском интерфейсе.

Из-за этого я не могу установить DataPropertyName в поле идентификатора. Это должно быть имя ссылки на класс, например:

DataGridViewComboBoxColumn dataGridViewComboBoxColumn = 
(DataGridViewComboBoxColumn)myDataGridView.Columns("LicenseComboBoxColumn");

dataGridViewComboBoxColumn.DataPropertyName = "License"; // not LicenseID

**** Обновление **** Я смог заставить это работать частично без создания свойства ProductId, указав Product. Id в качестве DataPropertyName следующим образом:

dataGridViewComboBoxColumn.DataPropertyName = "License.Id";

Однако при этом он нарушил привязку данных, что заставило меня вручную получить и установить значение ячейки.

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

// populate the combo box with Products for each License

foreach (DataGridViewRow row in myDataGridViewProducts.Rows) 
{
    IProduct myProduct = row.DataBoundItem as IProduct;
    DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)row.Cells("myProductCol");
    cell.DataSource = getListOfILicenseObjectsFromDao(myProduct.Id);
    cell.Value = myProduct.License.Id;
}

Может я что-то не так делаю, или может есть другой способ. Кто-нибудь может здесь помочь?

Вопрос 2:

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

1 ответ

Решение

Я нашел ответ сам. У меня была такая же проблема некоторое время назад, и я нашел решение в каком-то старом коде, который я выкопал. Решением было добавить свойство Self к объекту, к которому я хотел бы привязать данные в комбинированном списке (в приведенном выше примере это был бы класс License), и использовать это свойство как ValueMember следующим образом:

foreach (DataGridViewRow row in myDataGridViewProducts.Rows) 
{
    IProduct myProduct = row.DataBoundItem as IProduct;
    DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)row.Cells("myProductCol");
    cell.DataSource = getListOfILicenseObjectsFromDao(myProduct.Id);
    cell.DataPropertyName = "License";        
    cell.DisplayMember = "Name";
    cell.ValueMember = "Self"; // key to getting the databinding to work
    // no need to set cell.Value anymore!
}

Класс License теперь выглядит так:

Public class License
{
    public string Name
    {
        get; set;
    }

    public ILicense Self
    {
        get { return this; }
    }

    // ... more properties
}

Конечно, мне пришлось "испортить" бизнес-классы свойством Self, но это гораздо лучше (менее запутанно для программиста), чем иметь ссылку на свойство License и LicenseId в классе Product IMO. Кроме того, он значительно упрощает код пользовательского интерфейса, так как нет необходимости вручную получать и устанавливать значения - достаточно просто связать данные и все готово.