如何将枚举绑定到下拉框?

40
我希望将枚举类型的值与组合框控件绑定。
我编写了以下代码:
cboPriorLogicalOperator.DataSource = Enum.GetValues(typeof(MyEnum))
    .Cast<MyEnum>()
    .Select(p => new { Key = (int)p, Value = p.ToString() })
    .ToList();

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

它工作得很好,但我想知道是否有更简单的方法。


如果你的解决方案有效,为什么要寻找更简单的解决方案呢? - Security Hound
@ Ramhound:我认为可能有一种直接的方法。我确实理解我的代码,但并不是每个人都能简单地做到这一点。因此,我寻找了一种更简单的方法。 - Homam
1
@Homam 我不知道你是否有意这样做,但是当我模仿你的代码来解决我的问题时,我不得不在选择语句中反转键和值类型,以便正确地在组合框中显示值。你的方法最终在组合框中显示了键。 - gonzobrains
2
+1 对于问题提供实际答案! - gonzobrains
@gonzobrains 已修复。 - Homam
5个回答

24

我认为你的代码很漂亮!

唯一的改进是将代码放在一个扩展方法中。

编辑:

仔细想想,你想做的是像定义中那样使用Enum而不是枚举实例,这是扩展方法所需的。

我找到了这个问题,它解决得非常好:

public class SelectList
{
    // Normal SelectList properties/methods go here

    public static SelectList Of<T>()
    {
       Type t = typeof(T);
       if (t.IsEnum)
       {
           var values = from Enum e in Enum.GetValues(t)
                        select new { ID = e, Name = e.ToString() };
           return new SelectList(values, "Id", "Name");
       }
       return null;
    }
}

// called with 
var list = SelectList.Of<Things>();

只有你可能想要返回一个 Dictionary<int, string> 而不是一个 SelectList,但你能理解这个思路。

编辑2:

下面是一个涵盖你所关注的情况的代码示例。

public class EnumList
{
    public static IEnumerable<KeyValuePair<T, string>> Of<T>()
    {
        return Enum.GetValues(typeof (T))
            .Cast<T>()
            .Select(p => new KeyValuePair<T, string>(p, p.ToString()))
            .ToList();
    }
}

也许是这个版本,其中关键字是一个 int
public class EnumList
{
    public static IEnumerable<KeyValuePair<int, string>> Of<T>()
    {
        return Enum.GetValues(typeof (T))
            .Cast<T>()
            .Select(p => new KeyValuePair<int, string>(Convert.ToInt32(p), p.ToString()))
            .ToList();
    }
}

我同意。我们已经将winforms组合框扩展为我们自己的版本,并在其上拥有一个非常好用的BindToEnum<T>方法。它看起来很像这段代码。 - captncraig
啊,原始示例中漏掉了那个。在你的情况下,我认为它会返回 Dictionary<int, string> - Mikael Östberg
我添加了一些实际的代码,你应该能够使用。 我使用了IEnumerable<KeyValuePair<int,string>> ,因为当我使用枚举HttpStatusCode进行测试时,我遇到了键重复问题,这使我选择了这个而不是Dictionary<int,string>)。 但是,当使用int作为键时,不会发生重复错误。 - Mikael Östberg

6

为什么不要使用:

myComboBox.DataSource  = Enum.GetValues(typeof(MyEnum))

?


因为这不绑定键/值对。要从组合框中获取值,您必须将SelectedItem强制转换为枚举。请参见http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx的备注部分。 - Robert Harvey
我认为如果我们想在检索到的数据中设置条件,那么这段代码还不错...否则你的代码更好。 - Ali

1
foreach (int r in Enum.GetValues(typeof(MyEnum))) 
{
     var item = new ListItem(Enum.GetName(typeof(MyEnum), r), r.ToString());
     ddl.Items.Add(item);
}

0

最近我遇到了一个问题,我有一个可空的枚举属性,需要将其绑定到ComboBox上。这是我想出的解决方案:

using System;
using System.Collections.Generic;

namespace ActivitySchedule.Model
{
    public class NullableEnum<T> where T : struct, IComparable
    {
        public string Display { get; private set; }

        public T? Value { get; private set; }

        public static implicit operator T?(NullableEnum<T> o)
        {
            return o.Value;
        }

        public static implicit operator NullableEnum<T>(T? o)
        {
            return new NullableEnum<T>
            {
                Display = o?.ToString() ?? "NA",
                Value = o
            };
        }

        private NullableEnum() { }

        public static IEnumerable<NullableEnum<T>> GetList()
        {
            var items = new List<NullableEnum<T>>
            {
                new NullableEnum<T>
                {
                    Display = "NA",
                    Value = null
                }
            };

            var values = Enum.GetValues(typeof(T));

            foreach (T v in values)
            {
                items.Add(v);
            }

            return items;
        }
    }
}

我将对象封装在一个控制器类中,并像这样更改属性的类型:

private MyClass myClass;

public NullableEnum<MyEnum> MyEnum
{
    get { return this.myClass.MyEnum; }
    set { this.myClass.MyEnum = value.Value; }
}

它也可以是一个派生类并覆盖该属性

这是我使用它的方式:

var types = NullableEnum<MyEnum>.GetList();
this.comboBox1.DataSource = types;
this.comboBox1.DisplayMember = "Display";
this.comboBox1.ValueMember = "Value";
this.comboBox1.Bindings.Add("SelectedValue", myClassController, "MyEnum");

-1
private void Form1_Load(object sender, EventArgs e)
{
    comboBox1.DataSource = Enum.GetValues( typeof(Gender));
    Array gen = Enum.GetValues(typeof(Gender));
    List<KeyValuePair<string, char>> lstgender = new List<KeyValuePair<string,char>>();
    foreach(Gender g in gen)
        lstgender.Add(new KeyValuePair<string,char>(g.ToString(),((char)g)));
    comboBox1.DataSource = lstgender;
    comboBox1.DisplayMember = "key";
    comboBox1.ValueMember = "value"
}

private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(comboBox1.SelectedValue.ToString());
}

public class Student
{
    public string stud_name { get; set; }
    public Gender stud_gen { get; set; }
}

public enum Gender
{
    Male='M',
    Female='F'
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接