열거 형을 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를 사용하지 않는 이유는 무엇입니까?
Oliver Friedrich

5
귀하의 질문에 대한 답변이 있다면 정말 답을 선택해야합니다.
Ryan The Leach

열거 형 데이터 바인딩의 요점은 명확하지 않습니다. 열거 형은 런타임 중에 변경되지 않을 수 있습니다. 열거 형의 모든 값으로 콤보 상자의 항목 컬렉션을 채우는 확장 메서드를 작성할 수도 있습니다.
Andreas


@OliverFriedrich SelectedValueInvalidOperationException나를 위해 일합니다. "를 설정할 수 없습니다 SelectedValueA의를 ListControl빈으로 ValueMember."
Tyler

답변:


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

나를 위해 SelectedValue는 항상 null입니다. 콤보 박스가 초기화되지 않은 것 같습니다. (myEnum) this.GridView.CurrentRow.Cells [ "comboColumnCell"]. Value. 값을 볼 수 있지만 내부적으로 null 포인터 예외가 발생합니다.
ssal

3
이것은 OP가 사용하고 싶지 않은 방식입니다. 문제는 사용자에게 각 값의 코드에 이름이 표시된다는 것입니다. 이는 대부분 사용자 친화적이지 않고 리팩토링의 대상입니다.
Alejandro

5
Parse 대신 TryParse를 사용하는 이유는 무엇입니까? ... var status (Status) Enum.Parse (typeof (Status), cbStatus.SelectedValue.ToString ()); ... 열거 형을 콤보 상자에 바인딩하여 값이 유효한 열거 형 값이어야하고 그런 다음 무언가가 매우 잘못되어 예외를 원할 것입니다.
bytedev

1
왜 이것이 망각에 찬성 하는가? 문제는 열거 형 값 중 하나를 사용하여 콤보 상자의 선택된 값을 프로그래밍 방식으로 설정하는 방법입니다.
Tyler

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하고 바인딩 할 수 있습니다.
Alejandro

IMHO, 아마도 더 완전한 샘플 소스 코드, 검색에서 모든 행을 필터링하는 데 사용되는 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가"사용했다
티아구 Freitas의 충실한

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 2014 년

열거 번호가 OR FLag를 허용하는지 여부에 따라 다릅니다. 그렇다면 All이라는 255 플래그를 추가하고 All을 사용하여 함수를 enum1로 호출하여 기본값을 생성 할 수 있습니다. ie comboBox1.FillByEnumOrderByName (MyEnum.All)
Mickey Perlstein

다음과 같은 옵션 : var l = values.OrderBy (x => x.Value) .ToList (); l.Insert (0, "모두");
Kiquenet 2014 년

내 enum은 enum A {duck = 0, swan = 1, joker = 3}입니다. 당신의 시스템은 제 상황에 맞지 않을 것입니다.
Mickey Perlstein

3

이것은 combobox에 enum 항목을로드하는 솔루션입니다.

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

그런 다음 enum 항목을 텍스트로 사용하십시오.

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

3

@Amir Shenouda의 답변에 따라 다음과 같이 끝납니다.

Enum의 정의 :

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

드롭 다운 값 설정 :

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

선택한 항목에서 열거 형 가져 오기 :

Status? status = cbStatus.SelectedValue as Status?;

2
왜 nullable을 사용합니까? 당신은 널 (NULL) 사용 명시 적 캐스팅 (괄호 주조)을 사용 할 수 없습니다
존 데 메트

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
}

IMHO, 아마도 더 완전한 샘플 소스 코드, 검색에서 모든 행을 필터링하는 데 사용되는 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";
    }

그런 다음 데이터에 액세스하려면 다음 두 줄을 사용하십시오.

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

1

이것은 아마도 다른 모든 응답에서 볼 수 없을 것입니다. 그러나 이것이 제가 생각해 낸 코드입니다. 이것은 DescriptionAttribute존재한다면 사용하는 이점이 있지만 그렇지 않으면 열거 형 값 자체의 이름을 사용합니다.

미리 만들어진 키 / 값 항목 패턴이 있기 때문에 사전을 사용했습니다. A List<KeyValuePair<string,object>>는 불필요한 해싱 없이도 작동하지만 사전은 더 깨끗한 코드를 만듭니다.

나는이 회원 수 MemberTypeField그 리터럴됩니다. 이렇게하면 열거 형 값인 멤버의 시퀀스 만 생성됩니다. 열거 형은 다른 필드를 가질 수 없기 때문에 강력합니다.

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;

잘 작동해야합니다. 어떻게 SelectedItemnull 인지 알 수 있습니까?


디버거에서 확인할 수 있습니다. 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 }
Samantha Branham

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에서 ...와 같은 Sorted Enum이있는 경우

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 Form Combobox에서도 동일한 작업을 수행 할 수 있습니다.


0

이 파티에 조금 늦었 어

SelectedValue.ToString () 메서드는 DisplayedName을 가져와야합니다. 그러나이 문서는 DataBinding Enum 및 설명 포함 하는 편리한 방법을 보여줄뿐만 아니라 사용자 지정 설명 속성을 열거 형에 추가하고 원하는 경우 표시된 값에 사용할 수 있습니다. 매우 간단하고 쉽고 모든 것에 대해 약 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.