DataGridView基于枚举链接到带有Combobox列的DataTable

昨天花了很多时间搜索这个,我不得不放弃。

我有一个链接到Datatable的DataGridView。 其中一列是枚举,我希望它显示为Combobox列。

我在DataGridView中找到了这个链接创建下拉列表选项,其中包含使用以下内容的答案…

DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn(); col.Name = "My Enum Column"; col.DataSource = Enum.GetValues(typeof(MyEnum)); col.ValueType = typeof(MyEnum); dataGridView1.Columns.Add(col); 

我已经尝试了但是当用户创建一个新记录时,从下拉列表中选择一个选项(正确的选项显示)然后离开该字段,他们得到消息“DataGridViewComboBoxCel值无效”。 我在搜索中找到了一些解决方案,讨论如何捕获此错误,然后什么都不做(从而隐藏错误),但我想解决它而不是隐藏它。 如果用户确定了他们得到的消息,则重复另外两次。

我还看到了遍历枚举值的解决方案,并创建了一个包含int和每个字符串的数据表,然后使用数据表作为组合中的数据源。 在使用后端MSSQL数据库时,我曾使用数据表作为combobox的源代码。

另一种变体是循环并直接写入组合这样的…

  foreach (MyEnum bar in MyEnum.GetValues(typeof(MyEnum))) { string barName = MyEnum.GetName(typeof(MyEnum), bar); MyComboColumn.Items.Add(barName); } 

比如在这个链接中的问题。 如何将一些枚举值添加到combobox中

我的问题:可以使用Enum.GetValues(typeof(MyEnum))使其工作; 方法? 数据表方法看起来很长。 然后循环使用MyComboColumn.Items.Add(barName); 也有点长篇大论,并且会导致枚举的字符串版本记录在数据表中而不是整数(我宁愿它是整数)。

我找不到Enum.GetValues(typeof(MyEnum))方法的示例,其中网格链接到数据表。 当我搜索它时,我只是遇到了其他方法。

我认为问题可能在于基础表列上的数据类型。 我已经尝试过这个整数,作为一个字符串,我试过不定义它。 我想不出还有什么可以尝试这种类型。

这是我的简化代码。 (DVG是我表格上的DataGridView)。

 enum EngineType { None = 0, EngineType1 = 1, EngineType2 = 2 } public partial class MyClass : Form { DataTable DtTbl; public MyClass() { InitializeComponent(); CreateTableStructure(); } private void CreateTableStructure() { DGV.AutoGenerateColumns = false; DGV.DataSource = DtTbl; DtTbl = new DataTable(); DtTbl.Columns.Add(new DataColumn("Name", System.Type.GetType("System.String"))); DataGridViewTextBoxColumn NameCol = new DataGridViewTextBoxColumn(); NameCol.DataPropertyName = "Name"; NameCol.HeaderText = "Name"; DGV.Columns.Add(NameCol); DtTbl.Columns.Add(new DataColumn("Engine", System.Type.GetType("System.Int32"))); DataGridViewComboBoxColumn EngineCol = new DataGridViewComboBoxColumn(); EngineCol.DataPropertyName = "Engine"; EngineCol.HeaderText = "Engine"; //EngineCol.DataSource = EngineType.GetValues(typeof(EngineType)); foreach (EngineType engine in EngineType.GetValues(typeof(EngineType))) { string engineName = EngineType.GetName(typeof(EngineType), engine); EngineCol.Items.Add(engineName); } DGV.Columns.Add(EngineCol); } } 

我自己有这个问题,这是我如何解决它:

  DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn(); col.ValueType = typeof(MyEnum); col.ValueMember = "Value"; col.DisplayMember = "Display"; colElementtyp.DataSource = new MyEnum[] { MyEnum.Firstenumvalue, MyEnum.Secondenumvalue } .Select(value => new { Display = value.ToString(), Value = value }) .ToList(); 

DataGridViewComboBoxCell必须绑定到枚举或整数。 我想你的数据表的列是整数,那么它应该工作。

编辑:

这应该是动态的:

  System.Array enumarray = Enum.GetValues(typeof(MyEnum)); List lst = enumarray.OfType().ToList(); DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn(); col.ValueType = typeof(MyEnum); col.ValueMember = "Value"; col.DisplayMember = "Display"; colElementtyp.DataSource = lst .Select(value => new { Display = value.ToString(), Value = value }) .ToList(); 

更短

  DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn(); col.ValueType = typeof(MyEnum); col.ValueMember = "Value"; col.DisplayMember = "Display"; colElementtyp.DataSource = Enum.GetValues(typeof(MyEnum)).OfType().ToList() .Select(value => new { Display = value.ToString(), Value = value }) .ToList(); 

我放弃了这样做直接将枚举链接到combox。 我认为Koryu已经解决了它,但是当用户输入数据时它会起作用,如果我尝试以编程方式添加一行,并且枚举的有效值,它仍然会给出错误。

基于我的上述代码,随着Koryu的改变,我添加了这样的行。

 private void CreateDefaultRows() { DataRow Row = DtTbl.NewRow(); Row["Name"] = "FIN"; Row["Engine"] = EngineType.EngineType1; DtTbl.Rows.Add(Row); DGV.DataSource = DtTbl; } 

但尽管调试以确保有效值,我仍然得到错误。

我通过使用数据表的方法解决了它。 我在我的帮助器类中编写了一个generics方法,它返回任何枚举的数据表。

  public static DataTable Enum2DataTable() { DataTable EnumTable = new DataTable(); EnumTable.Columns.Add(new DataColumn("Value", System.Type.GetType("System.Int32"))); EnumTable.Columns.Add(new DataColumn("Display", System.Type.GetType("System.String"))); DataRow EnumRow; foreach (TE in Enum.GetValues(typeof(T))) { EnumRow = EnumTable.NewRow(); EnumRow["Value"] = E; EnumRow["Display"] = E.ToString(); EnumTable.Rows.Add(EnumRow); } return EnumTable; } 

如果我在问题代码中定义combobox列时添加以下行,一切正常,没有其他更改且没有错误。

 EngineCol.DataSource = Enum2DataTable(); 

虽然这是有效的,并且我有一个可重用的方法来再次执行此操作,但仍然感觉应该可以将枚举直接分配给combobox,因为“几乎”可以工作。

很想知道为什么它不起作用,但这个解决方案至少起作用。

使用RosieC的代码时,当枚举的基础类型不是Int32时,我仍然会得到exception。 这可以通过一个小修改来修复:

 public static DataTable Enum2DataTable() { DataTable EnumTable = new DataTable(); EnumTable.Columns.Add(new DataColumn("Value", Enum.GetUnderlyingType(typeof(T)))); EnumTable.Columns.Add(new DataColumn("Display", System.Type.GetType("System.String"))); DataRow EnumRow; foreach (TE in Enum.GetValues(typeof(T))) { EnumRow = EnumTable.NewRow(); EnumRow["Value"] = E; EnumRow["Display"] = E.ToString(); EnumTable.Rows.Add(EnumRow); } return EnumTable; }