2008-11-17 6 views
6

J'ai ma classe enumHelper qui contient ces:Obtenez la valeur Enum <T> Description de

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

et

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

mon ENUM est quelque chose comme:

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

Jusqu'à présent, si bien . Tout le travail précédent bien. Maintenant, je veux ajouter une nouvelle aide pour retourner BindingList>, donc je peux lier un ENUM à un combo en utilisant

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

Pour que j'ajouté:

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

Mais « Enum.Description (valeur) "n'est même pas en train de compiler: Argument '1': impossible de convertir 'T' en 'System.Enum'

Comment puis-je faire cela? Est-ce que c'est possible?

Merci.

+0

Votre méthode Description est-elle supposée être une méthode d'extension? Si c'est le cas, vous avez manqué le mot-clé this. –

+0

Voir ma réponse à cette question https://stackoverflow.com/questions/6145888/how-to-bind-an-enum-to-a-combobox-control-in-wpf/12430331#12430331 – Nick

Répondre

-2

Enum n'a pas de méthode Description(). Le mieux que vous puissiez faire est d'avoir votre enum implémentation d'une interface qui a la méthode Description(). Si vous faites cela, alors vous pouvez avoir

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

puis à l'intérieur de ce que vous pouvez consulter

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

Vous devez changer:

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

à

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

donc il accepte une valeur de l'énumération. Maintenant, voici où il devient difficile: vous avez une valeur, mais les attributs décorent le champ qui contient la valeur.

Vous devez réellement réfléchir sur les champs de l'énumération et vérifier la valeur de chacun contre la valeur que vous avez donné (les résultats doivent être mises en cache pour des performances):

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

Modifier aborder le suivi question

La méthode FillComboFromEnum ne contient pas le paramètre de type pour l'énumération. Essayez ceci:

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

Avis J'ai contraint le type à être struct. Ce n'est pas une contrainte d'énumération complète, mais c'est plus proche que rien.

6

Jetez un oeil à ce article. Vous pouvez le faire en utilisant le System.ComponentModel.DescriptionAttribute ou créer votre propre attribut:

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

Vous devez ensuite décorer les valeurs enum avec ce nouvel attribut:

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

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

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

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

    [EnumDescription("All")] 
    All 
} 

Toutes la « magie » se déroule dans les méthodes d'extension suivantes:

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

Enfin, vous pouvez simplement lier le combobox:

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

Oooor vous pourriez l'écrire dans votre réponse. – Henrik

+0

Au moins un résumé. – Henrik

+0

Y a-t-il une raison spécifique d'utiliser ArrayList ici? La liste ne serait-elle pas meilleure? – nawfal

Questions connexes