昨天花了很多时间搜索这个,我不得不放弃。
我有一个链接到Datatable的DataGridView。其中一列是enum,我希望它显示为Combobox列。
我发现此链接Create drop down list options from enum in a 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数据库时,我曾使用数据表作为组合框的源。
另一种变体是循环并直接写入组合,例如这......
foreach (MyEnum bar in MyEnum.GetValues(typeof(MyEnum)))
{
string barName = MyEnum.GetName(typeof(MyEnum), bar);
MyComboColumn.Items.Add(barName);
}
例如在此链接中的问题。 How can I add some Enum values to a 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);
}
}
答案 0 :(得分:2)
我自己有这个问题,这是我如何解决它:
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<MyEnum> lst = enumarray.OfType<MyEnum>().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<MyEnum>().ToList()
.Select(value => new { Display = value.ToString(), Value = value })
.ToList();
答案 1 :(得分:1)
我放弃了这样做直接将枚举链接到combox。我认为Koryu已经解决了它,但是当用户输入数据时它会起作用,如果我尝试以编程方式添加一行,并且枚举的有效值,它仍会给出错误。
基于我的上述代码,随着Koryu的改变,我添加了这样一行。
private void CreateDefaultRows()
{
DataRow Row = DtTbl.NewRow();
Row["Name"] = "FIN";
Row["Engine"] = EngineType.EngineType1;
DtTbl.Rows.Add(Row);
DGV.DataSource = DtTbl;
}
但是尽管调试以确保有效值,我仍然会收到错误。
我通过使用数据表的方法解决了它。我在我的帮助器类中编写了一个泛型方法,它返回任何枚举的数据表。
public static DataTable Enum2DataTable<T>()
{
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 (T E in Enum.GetValues(typeof(T)))
{
EnumRow = EnumTable.NewRow();
EnumRow["Value"] = E;
EnumRow["Display"] = E.ToString();
EnumTable.Rows.Add(EnumRow);
}
return EnumTable;
}
如果我在问题代码中定义组合框列时添加以下行,一切正常,没有其他更改且没有错误。
EngineCol.DataSource = Enum2DataTable<EngineType>();
虽然这有效,并且我有一个可重用的方法来再次执行此操作,但仍然觉得应该可以将枚举直接分配给组合框,因为“几乎”可以正常工作。
很想知道为什么它不起作用,但这种解决方案至少起作用。
答案 2 :(得分:1)
使用RosieC的代码,当枚举的基础类型不是Int32时,我仍然会得到异常。这可以通过一个小修改来修复:
public static DataTable Enum2DataTable<T>()
{
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 (T E in Enum.GetValues(typeof(T)))
{
EnumRow = EnumTable.NewRow();
EnumRow["Value"] = E;
EnumRow["Display"] = E.ToString();
EnumTable.Rows.Add(EnumRow);
}
return EnumTable;
}