2008-11-17 16 views
6

Mam klasę enumHelper który zawiera te:Pobierz Enum <T> wartość Opis

public static IList<T> GetValues() 
{ 
    IList<T> list = new List<T>(); 
    foreach (object value in Enum.GetValues(typeof(T))) 
    { 
    list.Add((T)value); 
    } 
    return list; 
} 

i

public static string Description(Enum value) 
{ 
    Attribute DescAttribute = LMIGHelper.GetAttribute(value, typeof(DescriptionAttribute)); 
    if (DescAttribute == null) 
    return value.ToString(); 
    else 
    return ((DescriptionAttribute)DescAttribute).Description; 
} 

mój enum jest coś takiego:

public enum OutputType 
{ 
    File, 
    [Description("Data Table")] 
    DataTable 
} 

tej pory tak dobrze . Cała poprzednia praca jest w porządku. Teraz chcę dodać nowego pomocnika, aby powrócić BindingList>, więc można połączyć dowolną enum do każdej combo używając

BindingList<KeyValuePair<OutputType, string>> list = Enum<OutputType>.GetBindableList(); 
cbo.datasource=list; 
cbo.DisplayMember="Value"; 
cbo.ValueMember="Key"; 

Do tego dodałam:

public static BindingList<KeyValuePair<T, string>> GetBindingList() 
{ 
    BindingList<KeyValuePair<T, string>> list = new BindingList<KeyValuePair<T, string>>(); 
    foreach (T value in Enum<T>.GetValues()) 
    { 
     string Desc = Enum<T>.Description(value); 
     list.Add(new KeyValuePair<T, string>(value, Desc)); 
    } 
    return list; 
} 

ale „Enum.Description (wartość) "nie kompiluje się: Argument" 1 ": nie można przekonwertować z" T "na" System.Enum "

Jak mogę to zrobić? Czy to w ogóle jest możliwe?

Dziękuję.

+0

Czy Twoja metoda opisu powinna być metodą rozszerzenia? Jeśli tak, przegapiłeś to słowo kluczowe. –

+0

Zobacz moją odpowiedź na to pytanie https://stackoverflow.com/questions/6145888/how-to-bind-an-enum-to-a-combobox-control-in-wpf/12430331#12430331 – Nick

Odpowiedz

-2

Enum nie ma metody Description(). Najlepsze co możesz zrobić, to mieć twój enum implementować interfejs, który ma metodę Description(). Jeśli to zrobisz, to możesz mieć

public static BindingList<KeyValuePair<T extends _interface_, String>> getBindingList() 

a następnie wnętrze, które można odnieść do

T foo = ...? 
foo.Description(...); 
3

należy zmienić:

public static string Description(Enum value) 
{ 
    ... 
} 

do

public static string Description(T value) 
{ 
    ... 
} 

, więc akceptuje wartość wyliczenia. Teraz jest tutaj, gdzie robi się trudno: masz wartość, ale atrybuty ozdobić w polu, które posiada wartość.

rzeczywiście trzeba zastanowić nad polami wyliczenia i sprawdzić wartość każdego z wartością zostałeś dany (wyniki powinny być buforowane dla wydajności):

foreach(var field in typeof(T).GetFields()) 
{ 
    T fieldValue; 

    try 
    { 
     fieldValue = (T) field.GetRawConstantValue(); 
    } 
    catch(InvalidOperationException) 
    { 
     // For some reason, one of the fields returned is {Int32 value__}, 
     // which throws an InvalidOperationException if you try and retrieve 
     // its constant value. 
     // 
     // I am unsure how to check for this state before 
     // attempting GetRawConstantValue(). 

     continue; 
    } 

    if(fieldValue == value) 
    { 
     var attribute = LMIGHelper.GetAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; 

     return attribute == null ? value.ToString() : attribute.Description; 
    } 
} 

Edit adresowania follow-up pytanie

W metodzie FillComboFromEnum brakuje parametru typu dla wyliczenia. Wypróbuj to:

public static void FillComboFromEnum<T>(ComboBox Cbo, BindingList<KeyValuePair<T, string>> List) where T : struct 

Zawiadomienie I ograniczyłem typ do struktury. To nie jest pełne ograniczenie wyliczeniowe, ale jest ono bliższe niż nic.

6

Proszę spojrzeć na to article. Możesz to zrobić za pomocą System.ComponentModel.DescriptionAttribute lub tworzenia własnego atrybutu:

/// <summary> 
/// Provides a description for an enumerated type. 
/// </summary> 
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, 
AllowMultiple = false)] 
public sealed class EnumDescriptionAttribute : Attribute 
{ 
    private string description; 

    /// <summary> 
    /// Gets the description stored in this attribute. 
    /// </summary> 
    /// <value>The description stored in the attribute.</value> 
    public string Description 
    { 
     get 
     { 
     return this.description; 
     } 
    } 

    /// <summary> 
    /// Initializes a new instance of the 
    /// <see cref="EnumDescriptionAttribute"/> class. 
    /// </summary> 
    /// <param name="description">The description to store in this attribute. 
    /// </param> 
    public EnumDescriptionAttribute(string description) 
     : base() 
    { 
     this.description = description; 
    } 
} 

następnie trzeba ozdobić wartości enum z tego nowego atrybutu:

public enum SimpleEnum 
{ 
    [EnumDescription("Today")] 
    Today, 

    [EnumDescription("Last 7 days")] 
    Last7, 

    [EnumDescription("Last 14 days")] 
    Last14, 

    [EnumDescription("Last 30 days")] 
    Last30, 

    [EnumDescription("All")] 
    All 
} 

Cała „magia” odbywa się w następujących metod rozszerzeń:

/// <summary> 
/// Provides a static utility object of methods and properties to interact 
/// with enumerated types. 
/// </summary> 
public static class EnumHelper 
{ 
    /// <summary> 
    /// Gets the <see cref="DescriptionAttribute" /> of an <see cref="Enum" /> 
    /// type value. 
    /// </summary> 
    /// <param name="value">The <see cref="Enum" /> type value.</param> 
    /// <returns>A string containing the text of the 
    /// <see cref="DescriptionAttribute"/>.</returns> 
    public static string GetDescription(this Enum value) 
    { 
     if (value == null) 
     { 
     throw new ArgumentNullException("value"); 
     } 

     string description = value.ToString(); 
     FieldInfo fieldInfo = value.GetType().GetField(description); 
     EnumDescriptionAttribute[] attributes = 
     (EnumDescriptionAttribute[]) 
     fieldInfo.GetCustomAttributes(typeof(EnumDescriptionAttribute), false); 

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

    /// <summary> 
    /// Converts the <see cref="Enum" /> type to an <see cref="IList" /> 
    /// compatible object. 
    /// </summary> 
    /// <param name="type">The <see cref="Enum"/> type.</param> 
    /// <returns>An <see cref="IList"/> containing the enumerated 
    /// type value and description.</returns> 
    public static IList ToList(this Type type) 
    { 
     if (type == null) 
     { 
     throw new ArgumentNullException("type"); 
     } 

     ArrayList list = new ArrayList(); 
     Array enumValues = Enum.GetValues(type); 

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

     return list; 
    } 
} 

Wreszcie, można po prostu powiązać combobox:

combo.DataSource = typeof(SimpleEnum).ToList(); 
+0

Oooor, możesz to napisać w twojej odpowiedzi. – Henrik

+0

Przynajmniej podsumowanie. – Henrik

+0

Czy istnieje jakiś szczególny powód używania ArrayList tutaj? Czy lista nie byłaby lepsza? – nawfal