2011-08-03 7 views
7

Mam enum tak:NET wiązania z danymi combobox do wyliczenia strun wraz z opisem atrybutów

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

Chcę powiązać to do combobox i próbowałem to:

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

Ale wyświetla wartości w combobox zamiast w opisie String. Więc przeszedłem do tego:

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; 
} 

Teraz list.Add() powoduje wywołanie w wartości i opis ciąg jest wyświetlany w combobox więc wymieniłem

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

z

list.Add(GetEnumDescription(value)); 

, a teraz otrzymuję tylko opisowy ciąg znaków wyświetlony na comboboxie, czego ostatecznie chcę. Teraz moje powiązanie danych jest zepsute, ponieważ nie może znaleźć tylko opisu ciągu w wyliczeniu. Pomyślałem, że może to być związane z combobox.DisplayMember i combobox.ValueMember, ale nie udało mi się jeszcze rozwiązać problemu. Czy ktokolwiek może mi powiedzieć, jak do cholery wyświetlam opisowy ciąg znaków, ale czy moje powiązanie danych używa wartości do przechowywania itp.? Dziękuję Ci!!!

+0

Po prostu z ciekawości .. dlaczego musisz używać do tego Enum? –

+0

Potrzebuję wyświetlić kilka comboboxes, które zawierają różne stałe opcje do wyboru dla moich użytkowników. Być może istnieje combobox wyświetlający cztery kolory (czerwony, żółty, zielony, niebieski). Inny może wyświetlić listę kształtów do wyboru. Ponieważ są to stałe listy, myślałem, że enum miałoby sens.Mam klasę "data", która modeluje wszystkie te rzeczy, a kiedy użytkownik zakończy wybory w interfejsie, po prostu analizuję właściwości obiektu danych i zapisuję wartości w pliku. Czy to jest odpowiedź na Twoje pytanie? – user685869

+0

Tak, i będzie działało dobrze tak, jak to robisz, tylko sprawia, że ​​kod jest trochę trudniejszy. Ponieważ i tak jest to lista zakodowana na stałe, jaka byłaby wada tworzenia listy zakodowanej na stałe w środowisku wykonawczym jako alternatywa? –

Odpowiedz

9

Wróćmy do pytania I answered kilka dni temu i zmodyfikujmy to, aby spełnić nowe wymagania. Tak więc zachowam przykład colorEnum zamiast twojego enumeratywnego Cities w tym pytaniu.

Jesteś na dobrej drodze - masz kod, który ma przejść od enumu do łańcucha opisu; teraz musisz po prostu wrócić w drugą stronę.

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; 
    } 
} 

Teraz wziąć to, co trzeba było kilka dni temu ...

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

i po prostu zmienić go na to:

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

Tak jak wcześniej, można powiązać combobox SelectedItem wartość do FavoriteColorString. Nie musisz ustawiać właściwości DisplayMember lub ValueMember, jeśli nadal korzystasz z BindingSource, tak jak w drugim pytaniu, które zakładam, że jesteś.

i zmienić kod wypełniania combobox z:

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

do

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

Teraz masz najlepszy ze wszystkich światów. Użytkownik widzi opis, twój kod zawiera nazwy wyliczeniowe, a magazyn danych zawiera wartości wyliczeniowe.

+0

Dałeś mi wiele wspaniałych odpowiedzi w ciągu ostatniego tygodnia i bardzo doceniam pomoc i wyjaśnienia. Jak zawsze, dziękuję za dzielenie się swoją wiedzą! – user685869

+1

@ user68: Nie ma za co. Nawiasem mówiąc, powodem, dla którego usunąłem kontrolę 'attributes! = Null' w' GetEnumDescription() 'jest to, że' GetCustomAttributes() 'zwraca pustą tablicę, gdy nie znajdzie żadnych atrybutów. –

+0

@ user68: i jeszcze jedna rzecz ... możesz przegłosować moje odpowiedzi, a także je zaakceptować. Doceniam każdy przedstawiciel, który mogę zarobić. :) –