使用 ComboBox 将 DataGridView 绑定到 DataTable 不起作用
Binding DataGridView to DataTable with ComboBox not working
我正在尝试创建一个绑定到 DataTable 的 DataGridView,其中一列是 ComboBox。代码运行但绑定后出现以下错误(不是绑定数据时):System.ArgumentException:DataGridViewComboBoxCell 值无效。
在 DataGridView 中,其中一列是 DataGridViewComboBoxColumn,它使用枚举(名为 structureType)作为其来源:
// ColumnStructure
//
this.ColumnStructure.ValueType = typeof(structureType);
this.ColumnStructure.DataSource = Enum.GetValues(typeof(structureType));
this.ColumnStructure.HeaderText = "Structure";
this.ColumnStructure.Name = "ColumnStructure";
this.ColumnStructure.DataPropertyName = "Structure";
//
当我在不使用 DataTable 的情况下填充 DataGridView 时,它工作正常:
structureType? structure = GetStructure(part);
dgvObjectTypes.Rows.Add(name, type, structure, count);
现在我想改用 DataTable,但无法正常工作。数据表创建如下:
DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Type", typeof(string));
table.Columns.Add("Structure", typeof(DataGridViewComboBoxCell));
table.Columns.Add("Count", typeof(int));
其他列工作得很好,但我无法使 "Structure" 列工作。以下是我尝试创建组合框的方法:
var cb = new DataGridViewComboBoxCell();
cb.ValueType = typeof(structureType);
cb.DataSource = Enum.GetValues(typeof(structureType));
cb.Value = (structureType)structure;
之后,我只为 table 创建行,并将 table 设置为 DataGridView 的数据源:
table.Rows.Add(name, type, cb, count);
dgv.DataSource = table;
我读过很多帖子,其中指出在组合框中使用枚举会导致问题(例如:DataGridView linked to DataTable with Combobox column based on enum),但这里似乎并非如此。我什至尝试使用显式类型化的字符串数组,但仍然出现相同的错误。我认为我对 DataGridViewComboBoxCell 做错了什么。
可能是什么问题?
您似乎缺少的步骤是为 CBO 提供名称和值。 DataTable
可以存值,DGV可以显示相关名称,但需要你帮忙提供翻译。
private enum structureType
{ None, Circle, Square, Pyramid}
...
dtStruct = new DataTable();
dtStruct.Columns.Add("Name", typeof(string));
dtStruct.Columns.Add("Type", typeof(string));
dtStruct.Columns.Add("Structure", typeof(structureType));
dtStruct.Columns.Add("Count", typeof(int));
// autogen columns == true
dgv2.DataSource = dtStruct;
// create DataSource as list of Name-Value pairs from enum
var cboSrc = Enum.GetNames(typeof(structureType)).
Select( x => new {Name = x,
Value = (int)Enum.Parse(typeof(structureType),x)
}
).ToList();
// replace auto Text col with CBO col
DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.ValueType = typeof(structureType);
cb.DataSource = cboSrc;
cb.DisplayMember = "Name"; // important
cb.ValueMember = "Value"; // important
cb.HeaderText = "Structure";
cb.DataPropertyName = "Structure"; // where to store the value
dgv2.Columns.Remove(dgv2.Columns[2]); // remove txt col
dgv2.Columns.Add(cb);
cb.DisplayIndex = 2;
// add data
dtStruct.Rows.Add("Ziggy", "Foo", structureType.Circle, 6);
第一部分创建DataTable
,请注意结构列类型为structureType
(或通常为int
)。 DataTable
将存储数据,而不是 DataGridViewComboBoxCell
元素。在数据来自数据库的情况下,该列将是 int
,因为 structureType
不是已知类型。
然后根据枚举名称和值创建 DataSource
。这为控件提供了显示名称并将值存储在 DataTable
.
中的方法
如果 DGV 设置为自动生成列,您需要将默认值 TextBoxColumn
替换为 ComboBoxColumn
。这是在设置 DataSource
之后但在添加任何数据之前完成的。当数据来自数据库时(因此通常没有空的类型 table),您可以使用 ColumnAdded 事件将一列换成另一列。
添加 CBO 列时重要的是设置 ValueMember
和 DsiplayMember
属性以提供值 <-> 名称转换和 DataPropertyName
以便知道存储位置DataTable
.
中的选定值
我正在尝试创建一个绑定到 DataTable 的 DataGridView,其中一列是 ComboBox。代码运行但绑定后出现以下错误(不是绑定数据时):System.ArgumentException:DataGridViewComboBoxCell 值无效。
在 DataGridView 中,其中一列是 DataGridViewComboBoxColumn,它使用枚举(名为 structureType)作为其来源:
// ColumnStructure
//
this.ColumnStructure.ValueType = typeof(structureType);
this.ColumnStructure.DataSource = Enum.GetValues(typeof(structureType));
this.ColumnStructure.HeaderText = "Structure";
this.ColumnStructure.Name = "ColumnStructure";
this.ColumnStructure.DataPropertyName = "Structure";
//
当我在不使用 DataTable 的情况下填充 DataGridView 时,它工作正常:
structureType? structure = GetStructure(part);
dgvObjectTypes.Rows.Add(name, type, structure, count);
现在我想改用 DataTable,但无法正常工作。数据表创建如下:
DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Type", typeof(string));
table.Columns.Add("Structure", typeof(DataGridViewComboBoxCell));
table.Columns.Add("Count", typeof(int));
其他列工作得很好,但我无法使 "Structure" 列工作。以下是我尝试创建组合框的方法:
var cb = new DataGridViewComboBoxCell();
cb.ValueType = typeof(structureType);
cb.DataSource = Enum.GetValues(typeof(structureType));
cb.Value = (structureType)structure;
之后,我只为 table 创建行,并将 table 设置为 DataGridView 的数据源:
table.Rows.Add(name, type, cb, count);
dgv.DataSource = table;
我读过很多帖子,其中指出在组合框中使用枚举会导致问题(例如:DataGridView linked to DataTable with Combobox column based on enum),但这里似乎并非如此。我什至尝试使用显式类型化的字符串数组,但仍然出现相同的错误。我认为我对 DataGridViewComboBoxCell 做错了什么。
可能是什么问题?
您似乎缺少的步骤是为 CBO 提供名称和值。 DataTable
可以存值,DGV可以显示相关名称,但需要你帮忙提供翻译。
private enum structureType
{ None, Circle, Square, Pyramid}
...
dtStruct = new DataTable();
dtStruct.Columns.Add("Name", typeof(string));
dtStruct.Columns.Add("Type", typeof(string));
dtStruct.Columns.Add("Structure", typeof(structureType));
dtStruct.Columns.Add("Count", typeof(int));
// autogen columns == true
dgv2.DataSource = dtStruct;
// create DataSource as list of Name-Value pairs from enum
var cboSrc = Enum.GetNames(typeof(structureType)).
Select( x => new {Name = x,
Value = (int)Enum.Parse(typeof(structureType),x)
}
).ToList();
// replace auto Text col with CBO col
DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.ValueType = typeof(structureType);
cb.DataSource = cboSrc;
cb.DisplayMember = "Name"; // important
cb.ValueMember = "Value"; // important
cb.HeaderText = "Structure";
cb.DataPropertyName = "Structure"; // where to store the value
dgv2.Columns.Remove(dgv2.Columns[2]); // remove txt col
dgv2.Columns.Add(cb);
cb.DisplayIndex = 2;
// add data
dtStruct.Rows.Add("Ziggy", "Foo", structureType.Circle, 6);
第一部分创建DataTable
,请注意结构列类型为structureType
(或通常为int
)。 DataTable
将存储数据,而不是 DataGridViewComboBoxCell
元素。在数据来自数据库的情况下,该列将是 int
,因为 structureType
不是已知类型。
然后根据枚举名称和值创建 DataSource
。这为控件提供了显示名称并将值存储在 DataTable
.
如果 DGV 设置为自动生成列,您需要将默认值 TextBoxColumn
替换为 ComboBoxColumn
。这是在设置 DataSource
之后但在添加任何数据之前完成的。当数据来自数据库时(因此通常没有空的类型 table),您可以使用 ColumnAdded 事件将一列换成另一列。
添加 CBO 列时重要的是设置 ValueMember
和 DsiplayMember
属性以提供值 <-> 名称转换和 DataPropertyName
以便知道存储位置DataTable
.