4

昨日、これを探すのに多くの時間を費やしたので、あきらめなければなりません。

Datatable にリンクされた DataGridView があります。列の 1 つは列挙型であり、それを 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 値が無効です」というメッセージが表示されます。このエラーをトラップする方法について話している検索でいくつかの解決策を見つけましたが、何もしない (したがってエラーを非表示にする) だけでなく、非表示にするだけでなく解決したいと考えています。ユーザーがメッセージを OK すると、さらに 2 回繰り返します。

また、列挙型の値をループして、それぞれの int と文字列を含むデータテーブルを作成し、そのデータテーブルをコンボのデータソースとして使用するソリューションも見てきました。過去に、バックエンドの MSSQL データベースを操作するときに、コンボボックスのソースとしてデータ テーブルを使用したことがあります。

これの別の変形は、このようなコンボをループして直接書き込むことです...

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

このリンクの質問のように。いくつかの Enum 値をコンボボックスに追加するにはどうすればよいですか

私の質問: 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

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