【问题标题】:Create DataGridView column that maps value from datasource创建从数据源映射值的 DataGridView 列
【发布时间】:2018-08-17 11:08:30
【问题描述】:

我有一个DataTable,其中包含一些数据,例如。像这样:

| id  |  name | type_id |
+-----+-------+---------+
| 0   |   joe |     156 |
| 1   | alice |      23 |

DataTable 中的数据来自 SQL 数据库。我也有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 列

注意:在我的真实场景中,映射比数字->字符串更复杂。涉及多个值。因此必须真正创建新列!

【问题讨论】:

  • 从我的测试来看,“IsNumber”函数在做什么还不清楚。如果组合框包含“admin”。 “user”等……然后当object cellVal = comboCell.Value; 行……总是会返回一个字符串“admin”“user”等。你说“我有办法将type_id查找到type_name”……但是我没有看到这一点。要点是,根据我对组合框的测试,IsNumber(cellVal) 方法总是会失败,因为组合框的值不是数字。你能弄清楚“IsNumber”方法到底在做什么吗?

标签: c# .net winforms datagridview datatable


【解决方案1】:

不清楚“type_id”映射到“type_name”的值。换句话说,目前如果“type_id”是int156,那么“type_name”就是string“admin”。 “type_id”中是否还有其他数字也会产生“admin”?

如果它是一对一的关系,那么带有此映射的DataTable 将适用于组合框,您可以将组合框列直接映射到网格DataTable. 示例,如果有是一对一的关系,那么组合框的 DataTable 将有两个属性,int 用于“type_id”,string 用于“type_name”。

用正确的映射填充表格,然后设置组合框的DataSource 指向该表格。将组合框DataPropertyName 设置为“type_id”会将此列映射到网格DataSource. 中的相同列名使用这种方法,用户将在组合框中看到“admin”“user”等...如果他们更改其值,网格中的DataTable 将自动更新int“type_id”值。无需手动设置值。如果组合框设置正确,则此方法有效。

下面是一个例子。

如果存在一对多关系,那么我可以发布另一种解决方案。以下是上述内容的一个示例。

表单有两个DataGridViews。两个网格都使用相同的DataTableDataSource. 顶部网格,只显示我们想要的两列……“name”和“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;
  }
}

【讨论】:

    猜你喜欢
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 2021-09-29
    • 1970-01-01
    • 2020-07-07
    相关资源
    最近更新 更多