Привязать разные записи к DataGridViewComboBoxCell из источника данных - PullRequest
3 голосов
/ 19 марта 2010

У меня есть следующие данные, которые я хочу отобразить в DataGridView:

DataEntry[] data = new[]{
        new DataEntry(){Name = "A", Entries = new []{ "1", "2"}},
        new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};

«Имя» будет простым полем TextBox, а «Записи» - ComboBox, где элементы для выбора являются элементами в списке.

Таким образом, в этом примере будет 2 строки (ниже показано, как будет выглядеть сетка данных):

       Name                         Entries

Row1 :    A                    <choice of "1" or "2">
Row1 :    B                    <choice of "1" or "2" or "3">

Мой вопрос: как мне связать эти данные ?! Я посмотрел на свойства DataPropertyName, DisplayMember и ValueMember ... но просто не могу разобраться с этим.

Ниже приведен код в его нынешнем виде - с комментарием, в котором мне нужно добавить волшебную пару строк для установки источника данных и т. Д. Для столбца Записи.

public partial class Form1 : Form
    {
        DataEntry[] data = new[]{
            new DataEntry(){Name = "A", Entries = new []{ "1", "2"}},
            new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};

        public Form1()
        {
            InitializeComponent();
            dataGridView1.AutoGenerateColumns = false;

            var nameCol = new DataGridViewTextBoxColumn();
            nameCol.DataPropertyName = "Name";

            var entriesCol = new DataGridViewComboBoxColumn();

                    //entriesCol. ???? = "Entries"; !!

            dataGridView1.Columns.AddRange(new DataGridViewColumn[] { nameCol, entriesCol });

            dataGridView1.DataSource = data;   
        }
    }


    public class DataEntry
    {
        public string Name { get; set; }
        public IEnumerable<string> Entries { get; set; }
    }

Ответы [ 2 ]

4 голосов
/ 22 марта 2010

Приходите сегодня утром, и через 10 минут у меня все заработало!

Спасибо, перейдите на это сообщение на форуме MSDN

Решение состоит в том, чтобы подписаться на событие «DataBindingComplete», а затем пройти через каждую строку и установить источник данных для каждой ComboBoxCell. Было бы неплохо иметь более элегантное решение - но эй - оно работает!

Ниже приведена рабочая версия примера кода, который я представил в исходном вопросе:

public partial class Form1 : Form
{
    DataEntry[] data = new[]{
        new DataEntry(){Name = "A", Entries = new []{ "1", "2", "3", "4"}},
        new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};


    string[] cols = new[] { "col1", "col2" };

    public Form1()
    {
        InitializeComponent();

        dataGridView1.AutoGenerateColumns = false;

        var nameCol = new DataGridViewTextBoxColumn();
        nameCol.DataPropertyName = "Name";

        var entriesCol = new DataGridViewComboBoxColumn();
        entriesCol.Name = "Entries";
        dataGridView1.Columns.AddRange(new DataGridViewColumn[] { nameCol, entriesCol });

        dataGridView1.DataSource = data;
        dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
    }

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridView1.Rows[i].Cells["Entries"];
            DataEntry entry = dataGridView1.Rows[i].DataBoundItem as DataEntry;

            comboCell.DataSource = entry.Entries;
            comboCell.Value = entry.Entries.First();
        }
    }
}

public class DataEntry
{
    public string Name { get; set; }
    public IEnumerable<string> Entries { get; set; }
}
1 голос
/ 01 января 2013

Мне недавно пришлось сделать это и найти другое решение.

Я использовал 2 BindingSources, чтобы выполнить работу. Первый используется для заполнения таблицы данных, а второй используется ComboBoxColumn и использует первый BindingSource, поскольку его DataSource ссылается на DataMember.

Вот объект DataObject, который мы могли бы связать:

class DataObject
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string [] ValueList { get; set; }
}

Файл конструктора будет выглядеть примерно так:

// dataGridView1
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
  this.nameDataGridViewTextBoxColumn,
  this.valueDataGridViewTextBoxColumn});
this.dataGridView1.DataSource = this.bindingSource1;
// bindingSource1
this.bindingSource1.DataSource = typeof(SomeNamespace.DataObject);
// valueListBindingSource
this.valueListBindingSource.DataMember = "ValueList";
this.valueListBindingSource.DataSource = this.bindingSource1;
// nameDataGridViewTextBoxColumn
this.nameDataGridViewTextBoxColumn.DataPropertyName = "Name";
// valueDataGridViewTextBoxColumn
this.valueDataGridViewTextBoxColumn.DataPropertyName = "Value";
this.valueDataGridViewTextBoxColumn.DataSource = this.valueListBindingSource;

Тогда простая форма может выглядеть так:

public Form1 ()
{
  InitializeComponent ();
  m_objects = new List<DataObject> {
    new DataObject { Name = "foo", ValueList = new [] { "1", "2", "3", "4" }},
    new DataObject { Name = "bar", ValueList = new [] { "a", "b", "c" }}
  };
  bindingSource1.DataSource = m_objects;
}
private IList<DataObject> m_objects;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...