我有一个DataTable
,其中包含一些数据,例如像这样:
| id | name | type_id |
+-----+-------+---------+
| 0 | joe | 156 |
| 1 | alice | 23 |
DataTable
中的数据来自SQL-ish数据库。我也有DataGridView
,应显示以下内容:
| name | type_name |
+-------+-----------+
| joe | admin |
| alice | user |
我有一种方法可以将type_id
查找到type_name
。我添加了DataGridViewComboBoxColumn
,当它更改时,我更新了基础表中的type_id
:
private void cellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// find the cell
DataGridViewCell cell = dataGridView[e.ColumnIndex, e.RowIndex];
string columnName = dataGridView.Columns[e.ColumnIndex]?.Name ?? "";
// check if combo cell is in this column for sure
if(cell is DataGridViewComboBoxCell comboCell)
{
// Only user type is subject to this event
if(columnName == "type_name")
{
// BIG NOTE: THE LOOKUP HERE COULD (and is) BE MORE COMPLEX!
// This is just an example for stack overflow
object cellVal = comboCell.Value;
// Only numeric values
// Combobox displays string names, but contains numeric values
if(cellVal!=null && IsNumber(cellVal))
{
// change the underlying datatable, not the grid view
dataTable.Rows[e.RowIndex]["type_id"] = cellVal;
}
}
}
}
但是我也想拥有一个相反的版本。加载DataGridView
时,组合框列中的值为空。我该如何编写一个片段代码,将值从DataTable列映射到 DataGridView列。
注意:在我的实际情况中,映射比数字->字符串还要复杂。涉及多个值。因此,必须真正创建新列!
答案 0 :(得分:1)
不清楚“ type_id”是什么值映射到“ type_name”。换句话说,当前,如果“ type_id”是int
156,则“ type_name”是string
“ admin”。 ”“ type_id”中是否还有其他数字也会产生“ admin”?
如果是一对一关系,则具有此映射的DataTable
将适用于组合框,您将能够将组合框列直接映射到网格DataTable.
例如,如果存在一对一关系,则组合框的DataTable
将具有两个属性,“ type_id”的int
和“ type_name”的string
。 ”
使用正确的映射填充表格,然后设置组合框的DataSource
指向该表格。将组合框DataPropertyName
设置为“ type_id”会将此列映射到网格DataSource.
中的相同列名。使用这种方法,用户将在以下位置看到“ admin”“ user”等...组合框,如果它们更改了其值,则网格中的DataTable
将自动更新int
“ type_id”值。无需手动设置值。如果正确设置了组合框,则可以使用此功能。
下面是一个示例。
如果存在一对多关系,那么我可以发布另一种解决方案。下面是上面描述的示例。
该表单有两个DataGridView
。两个网格都使用与DataTable
相同的DataSource.
顶部网格仅显示我们想要的两列……“名称”和“ type_id”。“ type_id”列是组合框列,将显示int
“ type_id”的正确“ type_name”。
连接顶部网格CurrentCellDirtyStateChanged
事件以更新底部网格上的DataSource
,以显示int
“ type_id”值在用户更改组合框单元格时自动更改值。
我希望这是有道理的。
DataTable dataTable;
DataTable comboData;
public Form2() {
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e) {
dataTable = GetTable();
FillTable(dataTable);
FillComboTable();
SetGridColumns(dataGridView1);
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = dataTable;
dataGridView2.DataSource = dataTable;
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("name", typeof(string));
dt.Columns.Add("type_id", typeof(int));
return dt;
}
private void FillTable(DataTable dt) {
dt.Rows.Add(0, "joe", 156);
dt.Rows.Add(1, "alice", 23);
dt.Rows.Add(2, "mark", 0);
dt.Rows.Add(3, "sally", 44);
dt.Rows.Add(4, "gabe", 133);
}
private DataTable GetComboTable() {
DataTable dt = new DataTable();
dt.Columns.Add("value", typeof(int));
dt.Columns.Add("name", typeof(string));
return dt;
}
private void FillComboTable() {
comboData = GetComboTable();
comboData.Rows.Add(156, "admin");
comboData.Rows.Add(23, "user");
comboData.Rows.Add(44, "database");
comboData.Rows.Add(133, "system");
comboData.Rows.Add(0, " ");
}
private void SetGridColumns(DataGridView dgv) {
DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
col1.HeaderText = "name";
col1.Name = "name";
col1.DataPropertyName = "name";
dgv.Columns.Add(col1);
DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn {
HeaderText = "type_id",
Name = "type_id",
DataPropertyName = "type_id",
DataSource = comboData,
DisplayMember = "name",
ValueMember = "value"
};
dgv.Columns.Add(combo);
}
private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e) {
MessageBox.Show("Data Error: " + e.Exception.Message);
}
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) {
if (dataGridView1.IsCurrentCellDirty) {
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
dataGridView2.DataSource = null;
dataGridView2.DataSource = dataTable;
}
}