(使用C#Visual Studio 2015,Windows窗体)
我有一个我希望在DataGridView(DGV)中显示的字符串列表。
DGV中的每一行都有:
每条记录中的每个ComboBox都有相同的项目(相同的DataSet),我将这些从SQL查询中检索到我的Access数据库(accdb)。
我的主要问题是我需要识别每个ComboBox的ValueMember
和DisplayMember
,而我无法弄清楚如何做到这一点。我当前的代码只是尝试将DataTable results
复制到ComboBox中,但我收到了错误:
System.ArgumentException.DataGridViewComboBoxCell value is not valid.
它会重复DataGridView中每个ComboBox的每个值。我无法弄清楚我做错了什么。
非常感谢任何帮助。这是代码:
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);
}
编辑:我刚检查一下我的查询是否通过添加此行来拉取记录:
MessageBox.Show(results.Rows.Count.ToString());
我收到了正确的记录数
答案 0 :(得分:0)
希望这可能会让事情变得清晰起来。很遗憾,DataGridViewComboBoxColumn
不是ComboBox
控件列。因此,以下行不会用作DataGridView
列。
ComboBox cb = new ComboBox();
cb.ValueMember = "ID";
cb.DisplayMember = "DESCRIP";
cb.DataSource = results;
DataGridView
有DataGridViewComboBoxColumn
,实际上比常规ComboBox
更具挑战性。所以为了帮助想象这一点,我制作了一张图画来展示我所描述的内容。
上面你可以看到下面代码的输出。我使用按钮单击放置断点来显示两个DataTables
。 DataGridViewComboBoxColumn
DataSource
是具有不同“设定点类型”的DataTable
,并在右侧显示“Id”和“设定点类型”0-14。这些是DataGridViewComboBoxColumn
用作DataSource.
方便的部分是,为此列设置DataSource
后,您不必使用每个新/现有单元更新此列。该列将自动构建ComboBoxCells
。当您使用所有数据为主DataTable
创建DataGridView
时,您会假设组合框列所在的单元格需要具有所有值。但是这些值只是一个匹配组合框中某个项目的字符串(希望如此)。因此,DataGridView
DataTable
(不是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);
}