2008-11-17 11 views
6

ich meine enumHelper Klasse, die diese enthält:die <T> Wert Beschreibung Enum Get

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

und

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

meine Enum ist so etwas wie:

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

So weit so gut . Alle vorherigen funktionieren gut. Jetzt möchte ich einen neuen Helfer hinzuzufügen Binding zurückzukehren>, so kann ich jede Enum einem Combo

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

Für die Verwendung verknüpfe ich hinzugefügt:

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

Aber „Enum.Description (Wert) "erstellt nicht einmal: Argument '1': Konvertierung von 'T' nach 'System.Enum' nicht möglich

Wie kann ich das tun? Ist das überhaupt möglich?

Vielen Dank.

+0

Soll Ihre Beschreibungsmethode eine Erweiterungsmethode sein? Wenn ja, haben Sie dieses Schlüsselwort verpasst. –

+0

Siehe meine Antwort auf diese Frage https://stackoverflow.com/questions/6145888/how-to-bind-an-enum-to-a-combobox-control-in-wpf/12430331#12430331 – Nick

Antwort

-2

Enum verfügt nicht über eine Description() - Methode. Das Beste, was Sie tun können, ist, dass Ihre Enum eine Schnittstelle mit der Description() -Methode implementiert. Wenn Sie das tun, dann können Sie

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

haben und dann innerhalb von, dass Sie

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

beziehen können, sollten Sie ändern:

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

zu

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

so akzeptiert es einen Wert der Aufzählung. Jetzt hier ist, wo es schwierig wird: Sie haben einen Wert, aber Attribute schmücken das Feld, das den Wert enthält.

Sie müssen tatsächlich über die Aufzählung der Felder reflektieren und prüfen Sie den Wert eines jeden gegen den Wert, den Sie erhalten hat (Ergebnisse sollen für die Leistung im Cache gespeichert werden):

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

bearbeiten Adressieren das Follow-up Frage

Der FillComboFromEnum Methode fehlt der Typparameter für die Enumeration. Versuchen Sie folgendes:

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

Beachten Sie, dass ich den Typ auf eine Struktur beschränkt habe. Es ist keine vollständige Aufzählungsbeschränkung, aber es ist näher als nichts.

6

Werfen Sie einen Blick auf diese article. Sie können dies mit dem System.ComponentModel tun.Description oder ein eigenes 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; 
    } 
} 

Sie müssen dann mit diesem neuen Attribute der ENUM-Wert dekorieren:

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

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

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

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

    [EnumDescription("All")] 
    All 
} 

Alle von der „Magie“ finden in den folgenden Erweiterungsmethoden:

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

Schließlich können Sie dann binden Sie einfach die Combobox:

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

Oooor man konnte es schreiben in deiner Antwort. – Henrik

+0

Mindestens eine Zusammenfassung. – Henrik

+0

Gibt es einen bestimmten Grund, ArrayList hier zu verwenden? Würde nicht Liste besser sein? – nawfal