2008-11-17 11 views
6

tengo mi clase enumHelper que contiene los siguientes:Obtener el Enum <T> valor Descripción

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

y

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

mi enumeración es algo así como:

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

Hasta aquí todo bien . Todo el trabajo previo está bien. Ahora quiero añadir un nuevo ayudante para volver BindingList>, por lo que se puede vincular cualquier enumeración a cualquier combo usando

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

Para que añade:

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

Pero "Enum.Description (valor) "ni siquiera está compilando: Argumento '1': no ​​se puede convertir de 'T' a 'System.Enum'

¿Cómo puedo hacer eso? ¿Es eso posible?

Gracias.

+0

¿Se supone que su método de descripción es un método de extensión? Si es así, te perdiste esta palabra clave. –

+0

Ver mi respuesta en esta pregunta https://stackoverflow.com/questions/6145888/how-to-bind-an-enum-to-a-combobox-control-in-wpf/12430331#12430331 – Nick

Respuesta

-2

Enum no tiene un método de descripción(). Lo mejor que puedes hacer es que tu enum implemente una interfaz que tenga el método Description(). Si lo hace, entonces puede tener

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

y luego dentro de la que se puede hacer referencia a

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

Debe cambiar:

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

a

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

por lo que acepta un valor de la enumeración. Ahora aquí es donde se vuelve complicado: tiene un valor, pero los atributos decoran el campo que contiene el valor.

que realmente necesita para reflexionar sobre los campos de la enumeración y comprobar el valor de cada uno con respecto al valor que le han dado (deben almacenarse en caché los resultados de rendimiento):

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

Editar abordar el seguimiento pregunta

Al método FillComboFromEnum le falta el parámetro de tipo para la enumeración. Pruebe esto:

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

Tenga en cuenta que restringí el tipo para ser una estructura. No es una restricción de enumeración completa, pero está más cerca que nada.

6

Echa un vistazo a este article. Puedes hacer esto usando System.ComponentModel.DescriptionAttribute o la creación de su propio atributo:

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

este caso es necesario para decorar los valores de enumeración con este nuevo atributo:

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

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

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

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

    [EnumDescription("All")] 
    All 
} 

Todos los de la "magia" se lleva a cabo en los siguientes métodos de extensión:

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

Por último, puede simplemente enlazar el cuadro combinado:

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

Oooor podría escribirlo en tu respuesta. – Henrik

+0

Al menos un resumen. – Henrik

+0

¿Hay alguna razón específica para usar ArrayList aquí? ¿No sería mejor la Lista ? – nawfal