.NET使用Description属性将组合框数据绑定到字符串枚举

时间:2011-08-03 01:38:32

标签: .net winforms data-binding combobox enumeration

我有一个这样的枚举:

public enum Cities
{
    [Description("New York City")]
    NewYork,
    [Description("Los Angeles")]
    LosAngeles,
    Washington,
    [Description("San Antonio")]
    SanAntonio,
    Chicago
}

我想将它绑定到一个组合框,我试过这个:

comboBox.DataSource = Enum.GetNames(typeof(Cities));

但是它显示组合框中的值而不是字符串描述。所以我改用了这个:

public static string GetEnumDescription(Enum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

    if (attributes != null && attributes.Length > 0)
    {
        return attributes[0].Description;
    }
    else
    {
        return value.ToString();
    }
}

public static IList ToList(this Type type)
{
    ArrayList list = new ArrayList();
    Array enumValues = Enum.GetValues(type);

    foreach (Enum value in enumValues)
    {
        list.Add(new KeyValuePair<Enum, string>(value, GetEnumDescription(value)));
    }

    return list;
}

现在list.Add()调用会产生值,并且它的字符串描述显示在组合框中,所以我替换了

list.Add(new KeyValuePair<Enum, string>(value, GetEnumDescription(value)));

list.Add(GetEnumDescription(value));

现在我只得到组合框中显示的描述性字符串,这是我最终想要的。现在我的数据绑定被破坏了,因为它无法在枚举中找到字符串描述。我认为这可能与combobox.DisplayMember和combobox.ValueMember有关,但我还没能解决问题。任何人都可以告诉我如何显示描述性字符串,但我的数据绑定使用值存储等?谢谢!!!

1 个答案:

答案 0 :(得分:9)

让我们回到几天前的answered问题并根据您的新要求进行修改。因此,我会在此问题中保留colorEnum示例代替您的Cities枚举。

你大部分都在那里 - 你已经有了从枚举到描述字符串的代码;现在你只需要回到另一个方向。

public static class EnumHelper
{
    // your enum->string method (I just decluttered it a bit :))
    public static string GetEnumDescription(Enum value)
    {
        var fi = value.GetType().GetField(value.ToString());
        var attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attributes.Length > 0)
            return ((DescriptionAttribute)attributes[0]).Description;
        else
            return value.ToString();        
    }

    // the method to go from string->enum
    public static T GetEnumFromDescription<T>(string stringValue)
        where T : struct
    {
        foreach (object e in Enum.GetValues(typeof(T)))           
            if (GetEnumDescription((Enum)e).Equals(stringValue))
                return (T)e;
        throw new ArgumentException("No matching enum value found.");
    }

    // and a method to get a list of string values - no KeyValuePair needed
    public static IEnumerable<string> GetEnumDescriptions(Type enumType)
    {
        var strings = new Collection<string>();
        foreach (Enum e in Enum.GetValues(enumType))   
            strings.Add(GetEnumDescription(e));
        return strings;
    }
}

现在,看看你几天前的情况......

public class Person 
{
    [...]
    public colorEnum FavoriteColor { get; set; }
    public string FavoriteColorString
    {
        get { return FavoriteColor.ToString(); }
        set { FavoriteColor = (colorEnum)Enum.Parse(typeof(colorEnum), value);  }
    }
}

然后将其更改为:

public class Person 
{
    [...]
    public colorEnum FavoriteColor { get; set; }
    public string FavoriteColorString
    {
        get { return EnumHelper.GetEnumDescription(FavoriteColor); }
        set { FavoriteColor = EnumHelper.GetEnumFromDescription<colorEnum>(value); }
    }
}

和以前一样,您将组合框SelectedItem绑定到FavoriteColorString。如果您仍在使用BindingSource,则无需设置DisplayMember或ValueMember属性,就像您在其他问题中一样,我认为您就是这样。

从以下位置更改组合框填充代码:

comboBoxFavoriteColor.DataSource = Enum.GetNames(typeof(colorEnum));

comboBoxFavoriteColor.DataSource = EnumHelper.GetEnumDescriptions(typeof(colorEnum));

现在你拥有最好的世界。用户看到描述,您的代码包含枚举名称,数据存储包含枚举值。