2017-02-13 16 views
0

(с помощью C# Visual Studio 2015, Windows Forms)Копировать ComboBox Dataset в DataGridViewComboBoxColumn

У меня есть список строк, которые я хочу показать в DataGridView (DGV).

Каждая строка в DGV будет иметь:

  • столбец [0]: строковое значение из списка (ColumnType: DataGridViewTextBoxColumn)
  • колонка [1]: пустая ячейки (пользователь будет вводить данные здесь) (ColumnType: DataGridViewTextBoxColumn)
  • колонка [2]: выпадающий (ColumnType: DataGridViewComboBoxColumn)

Каждый ComboBox в каждой записи будет иметь одинаковые элементы (тот же DataSet), и я извлекаю их из SQL-запроса в мою базу данных доступа (accdb).

Моя основная проблема заключается в том, что мне нужно идентифицировать ValueMember и DisplayMember каждого ComboBox, и я не могу понять, как это сделать. Мой текущий код просто пытается скопировать DataTable results в ComboBox, но я получаю сообщение об ошибке:
System.ArgumentException.DataGridViewComboBoxCell value is not valid.

enter image description here

И это повторяется для каждого значения каждого ComboBox в DataGridView. Я не могу понять, что я делаю неправильно.

Любая помощь была бы принята с благодарностью. Вот код:

 DataTable results = new DataTable(); 

    //Identify the Connection String 
    connection.ConnectionString = dbQuery.connStr; 

    //SQL Statement to retrieve ComboBox Items 
    string sql = @"SELECT ID, DESCRIP FROM tbl_setpoints_categories ORDER BY DESCRIP ASC"; 

    //Create a new ComboBox (this is for testing purposes) 
    ComboBox cb = new ComboBox(); 

     try 
     { 
      connection.Open(); 
      OleDbCommand command = new OleDbCommand(); 
      command.Connection = connection; 
      command.CommandText = sql; 
      OleDbDataReader reader = command.ExecuteReader(); 

      results.Columns.Add("ID", typeof(int)); 
      results.Columns.Add("DESCRIP", typeof(string)); 
      results.Load(reader); 

      //For testing purposes... 
      cb.ValueMember = "ID"; 
      cb.DisplayMember = "DESCRIP"; 
      cb.DataSource = results; 

      if (!reader.IsClosed) 
      { 
       reader.Close(); 
      } 
     } 
     finally 
     { 
      connection.Close(); 
     } 


     //Loop through the list and add each into an array of objects 
     //This array will be added as a DataGridView row 
     foreach (string spName in spList) 
     { 

      //My Latest Edit, but still produces same error 
      DataGridViewComboBoxCell cbCell = new DataGridViewComboBoxCell(); 
      cbCell.ValueMember = "ID"; 
      cbCell.DisplayMember = "DESCRIP"; 
      cbCell.DataSource = results; 
      //End Latest Edit 

      object[] row = new object[3]; 
      row[0] = spName.ToString(); 
      row[1] = ""; 
      row[2] = cbCell; //From Latest Edit (was: results) 
      dataGridView1.Rows.Add(row); 
     } 

EDIT: Я только что проверил, чтобы увидеть, если мой запрос тянул записи, добавив следующую строку:
MessageBox.Show(results.Rows.Count.ToString());
И я получил правильное число записей

+0

Возможный дубликат http://stackoverflow.com/questions/654829/datagridviewcomboboxcell-binding-value-is-not-valid –

ответ

0

Надеюсь, это может прояснить ситуацию. К сожалению, DataGridViewComboBoxColumn НЕ является столбцом ComboBox элементов управления. Таким образом, строки ниже не будут работать как столбец DataGridView.

ComboBox cb = new ComboBox(); 
cb.ValueMember = "ID"; 
cb.DisplayMember = "DESCRIP"; 
cb.DataSource = results; 

The DataGridView имеет DataGridViewComboBoxColumn, который, к сожалению, является немного более сложным для реализации, чем обычный ComboBox. Поэтому, чтобы визуализировать это, я сделал рисунок, чтобы показать, что я описываю.

enter image description here

Выше вы можете увидеть выход из приведенного ниже кода. Я использовал кнопку, чтобы разместить точку останова, чтобы отобразить два DataTables. DataGridViewComboBoxColumnDataSource - это DataTable с различными «Устанавливаемыми точками» и отображается справа, показывая «Id» и «Set Point Types» 0-14. Эти элементы, что DataGridViewComboBoxColumn использует в качестве DataSource.

Удачной части является то, что, как только вы установите DataSource для этого столбца не должна обновлять это с каждой новой/существующей ячейкой.Столбец автоматически построит ComboBoxCells. Когда вы создаете DataTable для основного DataGridView со всеми данными, вы можете предположить, что ячейки, в которых столбец со списком должны иметь ВСЕ значения. Но эти значения будут просто одной строкой, которая соответствует одному из элементов в поле со списком (надеюсь). Таким образом, столбец DataGridViewDataTable (а не столбец DataGridView) должен сделать этот столбец строкой (а не поле со списком), так как он может содержать только ОДНО значение из разных типов «Типы заданных точек». Удобный аспект заключается в том, что даже если это строка, а не поле со списком, если оно соответствует существующему элементу в поле со списком, оно отображает этот элемент.

Ниже приведен код, изображенный на картинке выше.

Сначала установите столбец DataGridView с двумя текстовыми столбцами, а затем последним столбцом является DataGridViewComboBoxColumn. Метод GetComboColumn возвращает DatGridViewComboBoxColumn с различными элементами для поля со списком. Здесь уместными являются DataPropertyName, DisplayMemeber и ValueMember, они определяют, какие столбцы использовать из DataSource. Ниже приведен метод добавления текстового столбца в DataTable.

И наконец, мы получаем DataTable для DataGridView с некоторыми тестовыми данными для тестирования. Надеюсь это поможет.

DataTable allData; 
DataTable comboTable; 

public Form1() { 
    InitializeComponent(); 
} 

//------------------------------------------------------------------------- 
private void Form1_Load(object sender, EventArgs e) { 
    SetDGVColumns(); 
    allData = GetAllData(); 
    dataGridView1.DataSource = allData; 
} 

private DataTable GetAllData() { 
    DataTable data = new DataTable(); 
    data.Columns.Add("Set Point Name", typeof(string)); 
    data.Columns.Add("Description", typeof(string)); 
    data.Columns.Add("Set Point Type", typeof(string)); // <-- NOTE: this is a string- not a combo box 

    data.Rows.Add("nai_m2_no2", "Description 0", "Set Point Type 4"); 
    data.Rows.Add("nao_enth_no3", "Description 1", "Set Point Type 13"); 
    data.Rows.Add("nai_m2_no4", "Description 2", "Set Point Type 4"); 
    data.Rows.Add("nai_m2_no5", "Description 3", "Set Point Type 11"); 
    data.Rows.Add("nai_m2_no6", "Description 4", "Set Point Type 3"); 
    data.Rows.Add("nai_m2_no7", "Description 5", "Set Point Type 2"); 
    return data; 
} 

//------------------------------------------------------------------------- 
private void SetDGVColumns() { 
    AddTextCol("Set Point Name"); 
    AddTextCol("Description"); 
    dataGridView1.Columns.Add(GetComboColumn()); // <-- THIS DataGridView Column needs to be a combo box column 
} 

//------------------------------------------------------------------------- 
private DataGridViewComboBoxColumn GetComboColumn() { 
    comboTable = new DataTable(); 
    comboTable.Columns.Add("ID", typeof(int)); 
    comboTable.Columns.Add("Set Point Type", typeof(string)); 
    for (int i = 0; i < 15; i++) { 
    comboTable.Rows.Add(i, "Set Point Type " + i); 
    } 
    // we now have a data table to use as a data source for the DataGridViewComboBoxColumn 
    // make a DataGridViewComboBoxColumn and set it properties 
    DataGridViewComboBoxColumn typeCol = new DataGridViewComboBoxColumn(); 
    typeCol.Width = 150; 
    typeCol.DataPropertyName = "Set Point Type"; //<-- needs to match the DataTable column name you want to display - in this case 'Set Point Type' 
    typeCol.HeaderText = "Set Point Type"; 
    typeCol.ValueMember = "Set Point Type"; 
    typeCol.DisplayMember = "Set Point Type"; 
    typeCol.Name = "Set Point Type"; 
    typeCol.DataSource = comboTable; 
    return typeCol; 
} 

//------------------------------------------------------------------------- 
private void AddTextCol(string colInfo) { 
    DataGridViewTextBoxColumn TextCol = new DataGridViewTextBoxColumn(); 
    TextCol.DataPropertyName = colInfo; 
    TextCol.HeaderText = colInfo; 
    TextCol.Name = colInfo; 
    dataGridView1.Columns.Add(TextCol); 
}