列挙型をWinFormsコンボボックスにバインドし、それを設定する


122

多くの人が、WinFormsでコンボボックスに列挙型をバインドする方法の質問に答えています。こんな感じです:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));

しかし、表示する実際の値を設定することができなければ、それはかなり役に立ちません。

私が試してみました:

comboBox1.SelectedItem = MyEnum.Something; // Does not work. SelectedItem remains null

私も試しました:

comboBox1.SelectedIndex = Convert.ToInt32(MyEnum.Something); // ArgumentOutOfRangeException, SelectedIndex remains -1

誰もこれを行う方法について何かアイデアがありますか?


2
代わりにComboBox.SelectedValueを試してみませんか?
オリバーフリードリヒ

5
あなたの質問に答えているなら、あなたは本当に答えを選ぶべきです。
Ryan The Leach 2013年

enumをデータバインドするポイントは明確ではありません。列挙型は実行時に変更されない可能性があります。また、コンボボックスの項目コレクションを列挙型のすべての値で埋める拡張メソッドを作成することもできます。
Andreas


@OliverFriedrich SelectedValueInvalidOperationException私にを引き起こします。「設定できませんSelectedValueListControl、空とValueMember。」
タイラー、

回答:


161

列挙型

public enum Status { Active = 0, Canceled = 3 }; 

そこからドロップダウン値を設定する

cbStatus.DataSource = Enum.GetValues(typeof(Status));

選択したアイテムから列挙型を取得する

Status status; 
Enum.TryParse<Status>(cbStatus.SelectedValue.ToString(), out status); 

5
ありがとう、これは私にとってはうまくいきます。tryparseは.net 4.0ステートメントであることを覚えておいてください。
real_yggdrasil 2012年

私にとって、SelectedValueは常にnullです。コンボボックスが初期化されていないようです。(myEnum)this.GridView.CurrentRow.Cells ["comboColumnCell"]。Value。値は確認できますが、内部的にはnullポインタ例外がスローされます
ssal

3
これはまさにOPが使用したくない方法です。問題は、ユーザーに各値のコードで名前が表示されることです。これはリファクタリングの対象であり、ほとんどの場合ユーザーフレンドリーではありません。
アレハンドロ

5
ParseではなくTryParseを使用する理由 ... var status(Status)Enum.Parse(typeof(Status)、cbStatus.SelectedValue.ToString()); ... enumをコンボボックスにバインドしたので、値は有効なenum値である必要があることを知っています。その場合、何かが非常に間違っており、おそらく例外が必要です。
bytedev

1
なぜこれが忘却に賛成されているのですか?問題は、列挙型の値の1つを使用して、コンボボックスの選択された値をプログラムで設定する方法です。
タイラー

39

簡略化するには:

最初にこのコマンドを初期化します:(例:の後InitalizeComponent()

yourComboBox.DataSource =  Enum.GetValues(typeof(YourEnum));

コンボボックスで選択したアイテムを取得するには:

YourEnum enum = (YourEnum) yourComboBox.SelectedItem;

コンボボックスの値を設定したい場合:

yourComboBox.SelectedItem = YourEnem.Foo;

2
これは、Display値がValueメンバーと同じである限り機能します。
ロードオブスクリプトスクリプト

15

コード

comboBox1.SelectedItem = MyEnum.Something;

問題ありません。問題はDataBindingにある必要があります。DataBindingの割り当ては、主にコンボボックスが最初に表示されるときに、コンストラクターの後で行われます。Loadイベントで値を設定してみてください。たとえば、次のコードを追加します。

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    comboBox1.SelectedItem = MyEnum.Something;
}

そして、それが機能するかどうかを確認します。


12

試してください:

comboBox1.SelectedItem = MyEnum.Something;

編集:

おっと、あなたはすでにそれを試しました。ただし、comboBoxがDropDownListに設定されている場合は、うまくいきました。

以下は、(DropDownとDropDownListの両方で)私のために働く私の完全なコードです:

public partial class Form1 : Form
{
    public enum BlahEnum
    { 
        Red,
        Green,
        Blue,
        Purple
    }

    public Form1()
    {
        InitializeComponent();

        comboBox1.DataSource = Enum.GetValues(typeof(BlahEnum));

    }

    private void button1_Click(object sender, EventArgs e)
    {
        comboBox1.SelectedItem = BlahEnum.Blue;
    }
}

興味深いことに、 `comboBox1.SelectedItem = BlahEnum.Blue;`を実行できるのは素晴らしいことですが、コンボボックスのアイテムを文字列にしたい場合(コンボボックスのアイテムを「チュアブルビタミンピル」にする場合など)はどうでしょう。
barlop

11

次の列挙型があるとします

public enum Numbers {Zero = 0, One, Two};

これらの値を文字列にマップするための構造体が必要です。

public struct EntityName
{
    public Numbers _num;
    public string _caption;

    public EntityName(Numbers type, string caption)
    {
        _num = type;
        _caption = caption;
    }

    public Numbers GetNumber() 
    {
        return _num;
    }

    public override string ToString()
    {
        return _caption;
    }
}

次に、すべての列挙型が文字列にマッピングされたオブジェクトの配列を返します。

public object[] GetNumberNameRange()
{
    return new object[]
    {
        new EntityName(Number.Zero, "Zero is chosen"),
        new EntityName(Number.One, "One is chosen"),
        new EntityName(Number.Two, "Two is chosen")
    };
}

次を使用して、コンボボックスにデータを入力します。

ComboBox numberCB = new ComboBox();
numberCB.Items.AddRange(GetNumberNameRange());

関数に渡したい場合に備えて、列挙型を取得する関数を作成します。

public Numbers GetConversionType() 
{
    EntityName type = (EntityName)numberComboBox.SelectedItem;
    return type.GetNumber();           
}

そして、あなたは大丈夫でなければなりません:)


+1いい解決策。最近この問題が発生し、同様の方法で解決されました(Tuple代わりにaを使用)。列挙値と説明の両方をプロパティに変換し、numberCB.DisplayProperty = "Caption"; `を追加して、直接numberCB.ValueProperty = "Num"使用SelectedValueしてバインドできるようにします。
アレハンドロ

私見、より完全なサンプルソースコードかもしれませんが、「すべて」/「すべて選択」オプションをComboBoxに追加するなどの機能があり、検索ですべての行をフィルタリングするために使用されます。
Kiquenet 2014年

5

これを試して:

// fill list
MyEnumDropDownList.DataSource = Enum.GetValues(typeof(MyEnum));

// binding
MyEnumDropDownList.DataBindings.Add(new Binding("SelectedValue", StoreObject, "StoreObjectMyEnumField"));

StoreObjectは、ストアMyEnum値のStoreObjectMyEnumFieldプロパティを持つ私のオブジェクトの例です。


1
これは断然最良のアプローチですが、それでも実際にはうまくいきませんでした。「SelectedValue」の代わりに「SelectedItem」を使用する必要があった
Tiago Freitas Leal

4
 public static void FillByEnumOrderByNumber<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select
                        new
                         KeyValuePair<TEnum, string>(   (enumValue), enumValue.ToString());

        ctrl.DataSource = values
            .OrderBy(x => x.Key)

            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }
    public static void  FillByEnumOrderByName<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true  ) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select 
                        new 
                         KeyValuePair<TEnum,string> ( (enumValue),  enumValue.ToString()  );

        ctrl.DataSource = values
            .OrderBy(x=>x.Value)
            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }

どういう意味ですか ?コメントを理解できませんでした。この拡張メソッドは機能します
Mickey Perlstein

これは、列挙型の数値がORフラグを許可するかどうかに依存します。その場合は、Allという255のフラグを追加し、Allをenum1として関数を呼び出すと、デフォルトが作成されます。ie comboBox1.FillByEnumOrderByName(MyEnum.All)
Mickey Perlstein '22 / 10/22

このようなオプション:var l = values.OrderBy(x => x.Value).ToList(); l.Insert(0、 "すべて");
Kiquenet 2014年

私の列挙型は列挙型A {ダック= 0、白鳥= 1、ジョーカー= 3}; あなたのシステムは私の状況では動作しません。
ミッキーペルスタイン2014年

3

これは、コンボボックスに列挙型のアイテムをロードするソリューションです:

comboBox1.Items.AddRange( Enum.GetNames(typeof(Border3DStyle)));

そして、列挙型アイテムをテキストとして使用します:

toolStripStatusLabel1.BorderStyle = (Border3DStyle)Enum.Parse(typeof(Border3DStyle),comboBox1.Text);

3

@Amir Shenoudaからの回答に基づいて、私はこれで終わります:

列挙型の定義:

public enum Status { Active = 0, Canceled = 3 }; 

そこからドロップダウン値を設定する:

cbStatus.DataSource = Enum.GetValues(typeof(Status));

選択したアイテムから列挙型を取得します:

Status? status = cbStatus.SelectedValue as Status?;

2
nullableを使用する理由 明示的なキャスト(かっこキャスト)を使用でき、nullを使用できない
John Demetriou

2
public Form1()
{
    InitializeComponent();
    comboBox.DataSource = EnumWithName<SearchType>.ParseEnum();
    comboBox.DisplayMember = "Name";
}

public class EnumWithName<T>
{
    public string Name { get; set; }
    public T Value { get; set; }

    public static EnumWithName<T>[] ParseEnum()
    {
        List<EnumWithName<T>> list = new List<EnumWithName<T>>();

        foreach (object o in Enum.GetValues(typeof(T)))
        {
            list.Add(new EnumWithName<T>
            {
                Name = Enum.GetName(typeof(T), o).Replace('_', ' '),
                Value = (T)o
            });
        }

        return list.ToArray();
    }
}

public enum SearchType
{
    Value_1,
    Value_2
}

私見、より完全なサンプルソースコードかもしれませんが、「すべて」/「すべて選択」オプションをComboBoxに追加するなどの機能があり、検索ですべての行をフィルタリングするために使用されます。
Kiquenet 2014年


1

リストにバインドできる次のヘルパーメソッドを使用します。

    ''' <summary>
    ''' Returns enumeration as a sortable list.
    ''' </summary>
    ''' <param name="t">GetType(some enumeration)</param>
    Public Shared Function GetEnumAsList(ByVal t As Type) As SortedList(Of String, Integer)

        If Not t.IsEnum Then
            Throw New ArgumentException("Type is not an enumeration.")
        End If

        Dim items As New SortedList(Of String, Integer)
        Dim enumValues As Integer() = [Enum].GetValues(t)
        Dim enumNames As String() = [Enum].GetNames(t)

        For i As Integer = 0 To enumValues.GetUpperBound(0)
            items.Add(enumNames(i), enumValues(i))
        Next

        Return items

    End Function

1

列挙型を文字列のリストに変換し、これをcomboBoxに追加します

comboBox1.DataSource = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();

selectedItemを使用して表示値を設定します

comboBox1.SelectedItem = SomeEnum.SomeValue;

1

これらはどれも私にとってはうまくいきませんでしたが、これはうまくいきました(そして、各列挙型の名前についてより良い説明を持つことができるという追加の利点がありました)。.netの更新によるものかどうかはわかりませんが、これが最善の方法だと思います。以下への参照を追加する必要があります。

System.ComponentModelを使用します。

enum MyEnum
{
    [Description("Red Color")]
    Red = 10,
    [Description("Blue Color")]
    Blue = 50
}

....

    private void LoadCombobox()
    {
        cmbxNewBox.DataSource = Enum.GetValues(typeof(MyEnum))
            .Cast<Enum>()
            .Select(value => new
            {
                (Attribute.GetCustomAttribute(value.GetType().GetField(value.ToString()), typeof(DescriptionAttribute)) as DescriptionAttribute).Description,
                value
            })
            .OrderBy(item => item.value)
            .ToList();
        cmbxNewBox.DisplayMember = "Description";
        cmbxNewBox.ValueMember = "value";
    }

次に、データにアクセスする場合は、次の2行を使用します。

        Enum.TryParse<MyEnum>(cmbxNewBox.SelectedValue.ToString(), out MyEnum proc);
        int nValue = (int)proc;

1

これはおそらく他のすべての応答では決して見られないでしょうが、これは私が思いついたコードです。これは、DescriptionAttribute存在する場合はそれを使用し、それ以外の場合は列挙値自体の名前を使用するという利点があります。

既製のキー/値アイテムパターンがあるため、ディクショナリを使用しました。A List<KeyValuePair<string,object>>も機能し、不必要なハッシュなしでも機能しますが、ディクショナリーはよりクリーンなコードを作成します。

私が持っているメンバー取得MemberTypeのをField、それはリテラルですが。これにより、列挙値であるメンバーのみのシーケンスが作成されます。列挙型は他のフィールドを持つことができないため、これは堅牢です。

public static class ControlExtensions
{
    public static void BindToEnum<TEnum>(this ComboBox comboBox)
    {
        var enumType = typeof(TEnum);

        var fields = enumType.GetMembers()
                              .OfType<FieldInfo>()
                              .Where(p => p.MemberType == MemberTypes.Field)
                              .Where(p => p.IsLiteral)
                              .ToList();

        var valuesByName = new Dictionary<string, object>();

        foreach (var field in fields)
        {
            var descriptionAttribute = field.GetCustomAttribute(typeof(DescriptionAttribute), false) as DescriptionAttribute;

            var value = (int)field.GetValue(null);
            var description = string.Empty;

            if (!string.IsNullOrEmpty(descriptionAttribute?.Description))
            {
                description = descriptionAttribute.Description;
            }
            else
            {
                description = field.Name;
            }

            valuesByName[description] = value;
        }

        comboBox.DataSource = valuesByName.ToList();
        comboBox.DisplayMember = "Key";
        comboBox.ValueMember = "Value";
    }


}

0
comboBox1.SelectedItem = MyEnum.Something;

正常に動作するはずです...それSelectedItemがnullであることをどのように確認できますか?


デバッガで確認できます。SelectedItemの型がオブジェクト、つまり参照型であり、列挙型が値型であるためだと思います。私はコンパイラがそれをキャッチすることを期待していましたが。

0

「FindString ..」関数を使用できます。

Public Class Form1
    Public Enum Test
        pete
        jack
        fran
        bill
    End Enum
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox1.DataSource = [Enum].GetValues(GetType(Test))
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact("jack")
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact(Test.jack.ToString())
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact([Enum].GetName(GetType(Test), Test.jack))
        ComboBox1.SelectedItem = Test.bill
    End Sub
End Class

0

KeyValuePair値のリストをコンボボックスのデータソースとして使用できます。enum型を指定でき、IEnumerable>を返すヘルパーメソッドが必要です。ここで、intはenumの値で、stringはenum値の名前です。コンボボックスで、DisplayMemberプロパティを「Key」に、ValueMemberプロパティを「Value」に設定します。ValueとKeyは、KeyValuePair構造のパブリックプロパティです。次に、行っているようにSelectedItemプロパティを列挙値に設定すると、機能するはずです。


0

現時点では、DataSourceではなくItemsプロパティを使用しています。これは、列挙値ごとにAddを呼び出す必要があることを意味しますが、それは小さな列挙型であり、とにかく一時コードです。

次に、値に対してConvert.ToInt32を実行し、SelectedIndexで設定できます。

一時的な解決策ですが、今のところYAGNIです。

アイデアを乾杯します。顧客からのフィードバックを得て適切なバージョンを作成するときに、おそらくそれらを使用します。



0
comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));

comboBox1.SelectedIndex = (int)MyEnum.Something;

comboBox1.SelectedIndex = Convert.ToInt32(MyEnum.Something);

これらはどちらも私にとってはうまくいきますか?


2
カスタム列挙値を使用する場合、これが機能するかどうかは不明です。enum MyEnum { Something = 47 }
たとえば

0

ドロップダウンのデータソースとして列挙型を設定するための一般的な方法

表示は名前になります。選択された値はEnum自体になります

public IList<KeyValuePair<string, T>> GetDataSourceFromEnum<T>() where T : struct,IConvertible
    {
        IList<KeyValuePair<string, T>> list = new BindingList<KeyValuePair<string, T>>();
        foreach (string value in Enum.GetNames(typeof(T)))
        {
            list.Add(new KeyValuePair<string, T>(value, (T)Enum.Parse(typeof(T), value)));
        }
        return list;
    }

0

それは常に問題でした。0から...のようなソートされた列挙型がある場合

public enum Test
      one
      Two
      Three
 End

.SelectedValueプロパティを使用する代わりに、名前をコンボボックスにバインドできます.SelectedIndex

   Combobox.DataSource = System.Enum.GetNames(GetType(test))

そしてその

Dim x as byte = 0
Combobox.Selectedindex=x

0

Framework 4では、次のコードを使用できます。

たとえば、MultiColumnMode列挙型をコンボボックスにバインドするには:

cbMultiColumnMode.Properties.Items.AddRange(typeof(MultiColumnMode).GetEnumNames());

選択したインデックスを取得するには:

MultiColumnMode multiColMode = (MultiColumnMode)cbMultiColumnMode.SelectedIndex;

注:この例ではDevExpressコンボボックスを使用していますが、Winフォームコンボボックスでも同じことができます


0

このパーティーに少し遅れて、

SelectedValue.ToString()メソッドはDisplayedNameを取得する必要があります。ただし、この記事のDataBinding EnumとWith Descriptionsは、それを簡単に実現できるだけでなく、カスタムの説明属性を列挙型に追加して、必要に応じて表示される値に使用することもできます。非常にシンプルで簡単、約15行程度のコード(中かっこを数えない限り)。

それはかなり気の利いたコードであり、あなたはそれをブートする拡張メソッドにすることができます...


0

この方法でのみキャストを使用します。

if((YouEnum)ComboBoxControl.SelectedItem == YouEnum.Español)
{
   //TODO: type you code here
}

0

拡張メソッドを使用できます

 public static void EnumForComboBox(this ComboBox comboBox, Type enumType)
 {
     var memInfo = enumType.GetMembers().Where(a => a.MemberType == MemberTypes.Field).ToList();
     comboBox.Items.Clear();
     foreach (var member in memInfo)
     {
         var myAttributes = member.GetCustomAttribute(typeof(DescriptionAttribute), false);
         var description = (DescriptionAttribute)myAttributes;
         if (description != null)
         {
             if (!string.IsNullOrEmpty(description.Description))
             {
                 comboBox.Items.Add(description.Description);
                 comboBox.SelectedIndex = 0;
                 comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
             }
         }   
     }
 }

使い方...列挙型宣言

using System.ComponentModel;

public enum CalculationType
{
    [Desciption("LoaderGroup")]
    LoaderGroup,
    [Description("LadingValue")]
    LadingValue,
    [Description("PerBill")]
    PerBill
}

このメソッドは、コンボボックス項目に説明を表示します

combobox1.EnumForComboBox(typeof(CalculationType));

0

これは私のために働きました:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
comboBox1.SelectedIndex = comboBox1.FindStringExact(MyEnum.something.ToString());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.