4

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

我有一个链接到数据表的 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 数据库时,我使用数据表作为组合框的源。

另一种变体是循环并直接写入组合中,例如......

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

例如在此链接中的问题中。如何将一些枚举值添加到组合框

我的问题:可以使用 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);

    }
}
4

3 回答 3

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();
于 2013-07-31T14:07:29.777 回答
1

我放弃了将枚举直接链接到组合框的操作。我认为 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>();

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

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

于 2013-08-18T18:20:23.403 回答
1

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

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;
}
于 2016-05-16T11:10:14.767 回答