.NET привязка данных комбинированного списка к строковому перечислению с атрибутами Description - PullRequest
7 голосов
/ 03 августа 2011

У меня есть такое перечисление:

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

Я хочу связать это со списком, и я попробовал это:

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

Но это отображает значения в выпадающем списке, а не описание String. Поэтому я перешел к этому:

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 Ответ

9 голосов
/ 07 августа 2011

Давайте вернемся к вашему вопросу, на который я ответил несколько дней назад, и изменим его в соответствии с вашими новыми требованиями. Поэтому я оставлю пример colorEnum вместо вашего Cities перечисления в этом вопросе.

Вы прошли большую часть пути - у вас есть код для перехода от enum к строке описания; теперь вам просто нужно вернуться в другую сторону.

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 Вам не нужно устанавливать свойства DisplayMember или ValueMember, если вы все еще используете BindingSource, как и в другом вопросе, который, как я полагаю, у вас есть.

И измените код заполнения поля со списком:

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

до

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

Теперь у вас есть лучшее из всех миров. Пользователь видит описание, ваш код содержит имена перечислений, а хранилище данных содержит значения перечислений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...