Comment puis-je avoir un combobox lié à enum avec un formatage de chaîne personnalisé pour les valeurs enum?

dans le post Enum ToString , une méthode est décrite pour utiliser l'attribut personnalisé DescriptionAttribute comme ceci:

Enum HowNice {
  [Description("Really Nice")]
  ReallyNice,
  [Description("Kinda Nice")]
  SortOfNice,
  [Description("Not Nice At All")]
  NotNice
}

et ensuite, vous appelez une fonction GetDescription , en utilisant une syntaxe comme:

GetDescription<HowNice>(NotNice); // Returns "Not Nice At All"

mais cela ne m'aide pas vraiment quand je veux simplement peupler un ComboBox avec les valeurs d'un enum, puisque je ne peux pas forcer le ComboBox à appeler GetDescription .

ce que je veux a les exigences suivantes:

  • Lire (HowNice)myComboBox.selectedItem sera de retour la valeur sélectionnée comme la valeur d'enum.
  • l'utilisateur doit voir les chaînes d'affichage conviviales, et pas seulement le nom des valeurs d'énumération. Donc, au lieu de voir " NotNice ", l'utilisateur, voir " Not Nice At All ".
  • avec un peu de chance, la solution exigera des changements de code minimes aux énumérations existantes.

évidemment, je pourrais mettre en œuvre une nouvelle classe pour chaque enum que je crée, et outrepasser son ToString() , mais c'est beaucoup de travail pour chaque enum, et je préfère éviter cela.

des idées?

bon, je vais même se lancer dans un hug comme un bounty :-)

132
demandé sur Community 2009-04-28 11:21:23

21 réponses

vous pouvez écrire un convertisseur de caractères qui lit les attributs spécifiés pour les rechercher dans vos ressources. Ainsi, vous obtiendriez la prise en charge de plusieurs langues pour afficher les noms sans trop de problèmes.

regardez dans les méthodes ConvertFrom/ConvertTo de la machine à écrire et utilisez la réflexion pour lire les attributs sur votre enum fields .

41
répondu sisve 2012-06-27 08:27:29

ComboBox a tout ce dont vous avez besoin: la propriété FormattingEnabled , que vous devriez définir à true , et Format événement, où vous aurez besoin de placer logique de formatage désirée. Ainsi,

myComboBox.FormattingEnabled = true;
myComboBox.Format += delegate(object sender, ListControlConvertEventArgs e)
    {
        e.Value = GetDescription<HowNice>((HowNice)e.Value);
    }
85
répondu Anton Gogolev 2009-04-28 07:36:31

Non! Les Enums sont des primitifs et non des objets UI-ce qui les fait servir L'UI .ToString () serait assez mauvais du point de vue de la conception. Vous essayez de résoudre le mauvais problème ici: le vrai problème est que vous ne voulez pas Enum.ToString() pour afficher dans la liste déroulante!

maintenant c'est un problème très solvable en effet! Vous créez un objet UI pour représenter les éléments de votre boîte bascule:

sealed class NicenessComboBoxItem
{
    public string Description { get { return ...; } }
    public HowNice Value { get; private set; }

    public NicenessComboBoxItem(HowNice howNice) { Value = howNice; }
}

Et puis il suffit d'ajouter des instances de cette classe la collection d'Articles de votre boîte bascule et définissez ces propriétés:

comboBox.ValueMember = "Value";
comboBox.DisplayMember = "Description";
44
répondu Sander 2009-04-28 07:33:25

TypeConverter. Je pense que c'est ce que je cherchais. All hail Simon Svensson !

[TypeConverter(typeof(EnumToStringUsingDescription))]
Enum HowNice {
  [Description("Really Nice")]
  ReallyNice,
  [Description("Kinda Nice")]
  SortOfNice,
  [Description("Not Nice At All")]
  NotNice
}

Tout ce que je dois changer dans mon enum actuel est d'ajouter cette ligne avant leur déclaration.

[TypeConverter(typeof(EnumToStringUsingDescription))]

une fois que je fais cela, n'importe quel enum sera affiché en utilisant le DescriptionAttribute de ses champs.

Oh, et le TypeConverter serait défini comme ceci:

public class EnumToStringUsingDescription : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return (sourceType.Equals(typeof(Enum)));
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return (destinationType.Equals(typeof(String)));
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (!destinationType.Equals(typeof(String)))
        {
            throw new ArgumentException("Can only convert to string.", "destinationType");
        }

        if (!value.GetType().BaseType.Equals(typeof(Enum)))
        {
            throw new ArgumentException("Can only convert an instance of enum.", "value");
        }

        string name = value.ToString();
        object[] attrs = 
            value.GetType().GetField(name).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return (attrs.Length > 0) ? ((DescriptionAttribute)attrs[0]).Description : name;
    }
}

This ça m'aide avec mon cas de ComboBox, mais il est évident que ça n'annule pas le ToString() . Je crois que je vais contenter de ce en attendant...

40
répondu Shalom Craimer 2017-05-23 12:17:53

en utilisant votre exemple d'énumération:

using System.ComponentModel;

Enum HowNice
{
    [Description("Really Nice")]
    ReallyNice,
    [Description("Kinda Nice")]
    SortOfNice,
    [Description("Not Nice At All")]
    NotNice
}

créer une Extension:

public static class EnumExtensions
{
    public static string Description(this Enum value)
    {
        var enumType = value.GetType();
        var field = enumType.GetField(value.ToString());
        var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute),
                                                   false);
        return attributes.Length == 0
            ? value.ToString()
            : ((DescriptionAttribute)attributes[0]).Description;
    }
}

alors vous pouvez utiliser quelque chose comme ce qui suit:

HowNice myEnum = HowNice.ReallyNice;
string myDesc = myEnum.Description();

voir: http://www.blackwasp.co.uk/EnumDescription.aspx pour plus d'information. Le crédit va à Richrd Carr pour la solution

30
répondu Tyler Durden 2012-08-01 01:45:58

vous pourriez faire une structure générique que vous pourriez utiliser pour tous vos enums qui ont des descriptions. Avec les conversions implicites vers et à partir de la classe, vos variables fonctionnent encore comme l'enum sauf pour la méthode ToString:

public struct Described<T> where T : struct {

    private T _value;

    public Described(T value) {
        _value = value;
    }

    public override string ToString() {
        string text = _value.ToString();
        object[] attr =
            typeof(T).GetField(text)
            .GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attr.Length == 1) {
            text = ((DescriptionAttribute)attr[0]).Description;
        }
        return text;
    }

    public static implicit operator Described<T>(T value) {
        return new Described<T>(value);
    }

    public static implicit operator T(Described<T> value) {
        return value._value;
    }

}

exemple d'utilisation:

Described<HowNice> nice = HowNice.ReallyNice;

Console.WriteLine(nice == HowNice.ReallyNice); // writes "True"
Console.WriteLine(nice); // writes "Really Nice"
8
répondu Guffa 2009-04-28 08:00:16

Je ne pense pas que vous pouvez le faire sans simplement lier à un type différent - du moins, pas commodément. Normalement, même si vous ne pouvez pas contrôler ToString() , vous pouvez utiliser un TypeConverter pour faire le formatage personnalisé - mais IIRC le truc System.ComponentModel ne respecte pas cela pour les énums.

vous pourriez vous lier à un string[] des descriptions, ou à quelque chose qui ressemble essentiellement à une paire clé/valeur? (description/valeur) - quelque chose comme:

class EnumWrapper<T> where T : struct
{
    private readonly T value;
    public T Value { get { return value; } }
    public EnumWrapper(T value) { this.value = value; }
    public string Description { get { return GetDescription<T>(value); } }
    public override string ToString() { return Description; }

    public static EnumWrapper<T>[] GetValues()
    {
        T[] vals = (T[])Enum.GetValues(typeof(T));
        return Array.ConvertAll(vals, v => new EnumWrapper<T>(v));
    }
}

Et puis lier à EnumWrapper<HowNice>.GetValues()

5
répondu Marc Gravell 2009-04-28 07:43:59

La meilleure façon de le faire est de faire une classe.

class EnumWithToString {
    private string description;
    internal EnumWithToString(string desc){
        description = desc;
    }
    public override string ToString(){
        return description;
    }
}

class HowNice : EnumWithToString {

    private HowNice(string desc) : base(desc){}

    public static readonly HowNice ReallyNice = new HowNice("Really Nice");
    public static readonly HowNice KindaNice = new HowNice("Kinda Nice");
    public static readonly HowNice NotVeryNice = new HowNice("Really Mean!");
}

je crois que c'est la meilleure façon de le faire.

lorsqu'il est fourré dans des comboboxes, le joli ToString sera affiché, et le fait que personne ne peut faire plus d'instances de votre classe en fait essentiellement un enum.

p. S. il faudra peut-être quelques corrections de syntaxe, Je ne suis pas très bon avec C#. (Java guy)

5
répondu jjnguy 2013-01-20 00:11:59

étant donné que vous préférez ne pas créer une classe pour chaque enum, je recommande la création d'un dictionnaire de la valeur d'enum/texte d'affichage et de lier cela à la place.

notez que ceci a une dépendance sur les méthodes de la méthode GetDescription dans le post original.

public static IDictionary<T, string> GetDescriptions<T>()
    where T : struct
{
    IDictionary<T, string> values = new Dictionary<T, string>();

    Type type = enumerationValue.GetType();
    if (!type.IsEnum)
    {
        throw new ArgumentException("T must be of Enum type", "enumerationValue");
    }

    //Tries to find a DescriptionAttribute for a potential friendly name
    //for the enum
    foreach (T value in Enum.GetValues(typeof(T)))
    {
        string text = value.GetDescription();

        values.Add(value, text);
    }

    return values;
}
3
répondu Richard Szalay 2009-04-28 07:36:06

impossible de remplacer le ToString() d'enums en C#. Toutefois, vous pouvez utiliser des méthodes d'extension;

public static string ToString(this HowNice self, int neverUsed)
{
    switch (self)
    {
        case HowNice.ReallyNice:
            return "Rilly, rilly nice";
            break;
    ...

bien sûr, vous devrez faire un appel explicite à la méthode, I. e;

HowNice.ReallyNice.ToString(0)

ce n'est pas une bonne solution, avec une déclaration d'interrupteur et tout - mais il devrait fonctionner et, espérons-le whitout à de nombreuses réécritures...

3
répondu Björn 2009-04-28 07:39:53

suite à la réponse de @scraimer, voici une version du convertisseur de type enum-to-string, qui supporte les drapeaux aussi bien:

    /// <summary>
/// A drop-in converter that returns the strings from 
/// <see cref="System.ComponentModel.DescriptionAttribute"/>
/// of items in an enumaration when they are converted to a string,
/// like in ToString().
/// </summary>
public class EnumToStringUsingDescription : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return (sourceType.Equals(typeof(Enum)));
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return (destinationType.Equals(typeof(String)));
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType.Equals(typeof(String)))
        {
            string name = value.ToString();
            Type effectiveType = value.GetType();          

            if (name != null)
            {
                FieldInfo fi = effectiveType.GetField(name);
                if (fi != null)
                {
                    object[] attrs =
                    fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    return (attrs.Length > 0) ? ((DescriptionAttribute)attrs[0]).Description : name;
                }

            }
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }

    /// <summary>
    /// Coverts an Enums to string by it's description. falls back to ToString.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public string EnumToString(Enum value)
    {
        //getting the actual values
        List<Enum> values = EnumToStringUsingDescription.GetFlaggedValues(value);
        //values.ToString();
        //Will hold results for each value
        List<string> results = new List<string>();
        //getting the representing strings
        foreach (Enum currValue in values)
        {
            string currresult = this.ConvertTo(null, null, currValue, typeof(String)).ToString();;
            results.Add(currresult);
        }

        return String.Join("\n",results);

    }

    /// <summary>
    /// All of the values of enumeration that are represented by specified value.
    /// If it is not a flag, the value will be the only value retured
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    private static List<Enum> GetFlaggedValues(Enum value)
    {
        //checking if this string is a flaged Enum
        Type enumType = value.GetType();
        object[] attributes = enumType.GetCustomAttributes(true);
        bool hasFlags = false;
        foreach (object currAttibute in attributes)
        {
            if (enumType.GetCustomAttributes(true)[0] is System.FlagsAttribute)
            {
                hasFlags = true;
                break;
            }
        }
        //If it is a flag, add all fllaged values
        List<Enum> values = new List<Enum>();
        if (hasFlags)
        {
            Array allValues = Enum.GetValues(enumType);
            foreach (Enum currValue in allValues)
            {
                if (value.HasFlag(currValue))
                {
                    values.Add(currValue);
                }
            }



        }
        else//if not just add current value
        {
            values.Add(value);
        }
        return values;
    }

}

et une méthode d'extension pour l'utiliser:

    /// <summary>
    /// Converts an Enum to string by it's description. falls back to ToString
    /// </summary>
    /// <param name="enumVal">The enum val.</param>
    /// <returns></returns>
    public static string ToStringByDescription(this Enum enumVal)
    {
        EnumToStringUsingDescription inter = new EnumToStringUsingDescription();
        string str = inter.EnumToString(enumVal);
        return str;
    }
2
répondu Avi Turner 2013-06-10 07:34:46

j'écrirais une classe générique à utiliser avec n'importe quel type. J'ai utilisé quelque chose comme ça dans le passé:

public class ComboBoxItem<T>
{
    /// The text to display.
    private string text = "";
    /// The associated tag.
    private T tag = default(T);

    public string Text
    {
        get
        {
            return text;
        }
    }

    public T Tag
    {
        get
        {
            return tag;
        }
    }

    public override string ToString()
    {
        return text;
    }

    // Add various constructors here to fit your needs
}

en plus de cela, vous pouvez ajouter une" méthode d'usine " statique pour créer une liste d'articles combobox donné un type enum (à peu près le même que la méthode Getdescriptionsque vous avez là). Ceci vous éviterait d'avoir à implémenter une entity par chaque type d'enum, et fournirait également un endroit agréable/logique pour la méthode d'aide "GetDescriptions" (personnellement I s'appellerait FromEnum (obj) ...

1
répondu Dan C. 2009-04-28 07:53:15

créer une collection qui contient ce dont vous avez besoin (comme des objets simples contenant une propriété Value contenant la valeur HowNice enum et une propriété Description contenant GetDescription<HowNice>(Value) et databind le combo à cette collection.

un peu comme ceci:

Combo.DataSource = new EnumeratedValueCollection<HowNice>();
Combo.ValueMember = "Value";
Combo.DisplayMember = "Description";

quand vous avez une classe de collection comme celle-ci:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Whatever.Tickles.Your.Fancy
{
    public class EnumeratedValueCollection<T> : ReadOnlyCollection<EnumeratedValue<T>>
    {
        public EnumeratedValueCollection()
            : base(ListConstructor()) { }
        public EnumeratedValueCollection(Func<T, bool> selection)
            : base(ListConstructor(selection)) { }
        public EnumeratedValueCollection(Func<T, string> format)
            : base(ListConstructor(format)) { }
        public EnumeratedValueCollection(Func<T, bool> selection, Func<T, string> format)
            : base(ListConstructor(selection, format)) { }
        internal EnumeratedValueCollection(IList<EnumeratedValue<T>> data)
            : base(data) { }

        internal static List<EnumeratedValue<T>> ListConstructor()
        {
            return ListConstructor(null, null);
        }

        internal static List<EnumeratedValue<T>> ListConstructor(Func<T, string> format)
        {
            return ListConstructor(null, format);
        }

        internal static List<EnumeratedValue<T>> ListConstructor(Func<T, bool> selection)
        {
            return ListConstructor(selection, null);
        }

        internal static List<EnumeratedValue<T>> ListConstructor(Func<T, bool> selection, Func<T, string> format)
        {
            if (null == selection) selection = (x => true);
            if (null == format) format = (x => GetDescription<T>(x));
            var result = new List<EnumeratedValue<T>>();
            foreach (T value in System.Enum.GetValues(typeof(T)))
            {
                if (selection(value))
                {
                    string description = format(value);
                    result.Add(new EnumeratedValue<T>(value, description));
                }
            }
            return result;
        }

        public bool Contains(T value)
        {
            return (Items.FirstOrDefault(item => item.Value.Equals(value)) != null);
        }

        public EnumeratedValue<T> this[T value]
        {
            get
            {
                return Items.First(item => item.Value.Equals(value));
            }
        }

        public string Describe(T value)
        {
            return this[value].Description;
        }
    }

    [System.Diagnostics.DebuggerDisplay("{Value} ({Description})")]
    public class EnumeratedValue<T>
    {
        private T value;
        private string description;
        internal EnumeratedValue(T value, string description) {
            this.value = value;
            this.description = description;
        }
        public T Value { get { return this.value; } }
        public string Description { get { return this.description; } }
    }

}

Comme vous pouvez le voir, cette collection est facilement personnalisable avec lambda à sélectionnez un sous-ensemble de votre recenseur et/ou implémentez un formatage personnalisé à string au lieu d'utiliser la fonction GetDescription<T>(x) que vous mentionnez.

1
répondu peSHIr 2009-04-28 08:13:19

vous pouvez utiliser PostSharp pour cibler Enum.ToString et ajouter le code aditionall que vous voulez. Cela ne nécessite aucun changement de code.

1
répondu majkinetor 2009-04-28 08:59:59

ce qu'il vous faut, c'est transformer un enum en une collection en lecture seule et lier la collection au combobox (ou à n'importe quelle paire de clés activée pour le contrôle de cette matière)

tout d'Abord vous avez besoin d'une classe pour contenir les éléments de la liste. Puisque tout ce dont vous avez besoin est la paire int/string, je vous suggère d'utiliser une interface et un combo de classe de base pour que vous puissiez implémenter la fonctionnalité dans n'importe quel objet que vous voulez:

public interface IValueDescritionItem
{
    int Value { get; set;}
    string Description { get; set;}
}

public class MyItem : IValueDescritionItem
{
    HowNice _howNice;
    string _description;

    public MyItem()
    {

    }

    public MyItem(HowNice howNice, string howNice_descr)
    {
        _howNice = howNice;
        _description = howNice_descr;
    }

    public HowNice Niceness { get { return _howNice; } }
    public String NicenessDescription { get { return _description; } }


    #region IValueDescritionItem Members

    int IValueDescritionItem.Value
    {
        get { return (int)_howNice; }
        set { _howNice = (HowNice)value; }
    }

    string IValueDescritionItem.Description
    {
        get { return _description; }
        set { _description = value; }
    }

    #endregion
}

Voici l'interface et un échantillon la classe qui l'implémente.Notez que la clé de la classe est fortement tapée sur L'Enum, et que les propriétés IValueDescritionItem sont explicitement implémentées (de sorte que la classe peut avoir n'importe quelles propriétés et vous pouvez choisir celles qui implémentent la paire clé/valeur.

maintenant la classe EnumToReadOnlyCollection:

public class EnumToReadOnlyCollection<T,TEnum> : ReadOnlyCollection<T> where T: IValueDescritionItem,new() where TEnum : struct
{
    Type _type;

    public EnumToReadOnlyCollection() : base(new List<T>())
    {
        _type = typeof(TEnum);
        if (_type.IsEnum)
        {
            FieldInfo[] fields = _type.GetFields();

            foreach (FieldInfo enum_item in fields)
            {
                if (!enum_item.IsSpecialName)
                {
                    T item = new T();
                    item.Value = (int)enum_item.GetValue(null);
                    item.Description = ((ItemDescription)enum_item.GetCustomAttributes(false)[0]).Description;
                    //above line should be replaced with proper code that gets the description attribute
                    Items.Add(item);
                }
            }
        }
        else
            throw new Exception("Only enum types are supported.");
    }

    public T this[TEnum key]
    {
        get 
        {
            return Items[Convert.ToInt32(key)];
        }
    }

}

donc tout ce dont vous avez besoin dans votre code est:

private EnumToReadOnlyCollection<MyItem, HowNice> enumcol;
enumcol = new EnumToReadOnlyCollection<MyItem, HowNice>();
comboBox1.ValueMember = "Niceness";
comboBox1.DisplayMember = "NicenessDescription";
comboBox1.DataSource = enumcol;

rappelez-vous que votre collection est tapée avec MyItem donc la valeur de combobox doit retourner une valeur enum si vous vous liez à la proprtie appropriée.

j'ai ajouté la propriété T this[Enum t] pour rendre la collection encore plus utile qu'un simple Combo consommable, par exemple textBox1.Text = enumcol[HowNice.ReallyNice].NicenessDescription;

vous pouvez bien sûr choisir de transformer MyItem en une classe clé / valeur utilisée seulement pour cette puprose sautant effectivement MyItem dans les arguments de type de EnumToReadnlyCollection tout à fait, mais alors vous seriez forcé d'aller avec int pour la clé (ce qui signifie obtenir combobox1.SelectedValue retournerait int et pas le type enum). Vous travaillez autour de cela si vous créez une classe KeyValueItem pour remplacer MyItem et ainsi de suite et ainsi de suite...

1
répondu 2009-06-25 14:36:27

Désolé d'avoir mis ce vieux fil.

j'utiliserais la méthode suivante pour localiser enum, car il peut afficher des valeurs significatives et localisées à l'utilisateur, et pas seulement une description, à travers un champ de texte dropdownlist dans cet exemple.

tout d'abord, je crée une méthode simple appelée OwToStringByCulture pour obtenir des chaînes localisées à partir d'un fichier global resources, dans cet exemple C'est BiBongNet.resx dans le dossier App_GlobalResources. Dans ce fichier de ressources, assurez-vous que toutes les chaînes sont identiques aux valeurs de l'enum (ReallyNice, SortOfNice, NotNice). Dans cette méthode, je passe dans le paramètre: resourceClassName qui est habituellement le nom du fichier de ressources.

ensuite, je crée une méthode statique pour remplir une dropdownlist avec enum comme source de données, appelée OwFillDataWithEnum. Cette méthode peut être utilisée avec n'importe quel enum plus tard.

puis dans la page avec une dropdownlist appelée DropDownList1, j'ai mis dans le Page_Load ce qui suit est une simple ligne de code pour remplir l'enum de la dropdownlist.

 BiBongNet.OwFillDataWithEnum<HowNice>(DropDownList1, "BiBongNet");

C'est ça. Je pense qu'avec quelques méthodes simples, vous pouvez remplir une liste de contrôle avec toute enum, pas seulement en tant que valeurs descriptives mais localisée texte à afficher. Vous pouvez faire toutes ces méthodes comme les méthodes d'extension pour une meilleure utilisation.

Espérons que cette aide. Partager pour partager!

Voici les méthodes:

public class BiBongNet
{

        enum HowNice
        {
            ReallyNice,
            SortOfNice,
            NotNice
        }

        /// <summary>
        /// This method is for filling a listcontrol,
        /// such as dropdownlist, listbox... 
        /// with an enum as the datasource.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ctrl"></param>
        /// <param name="resourceClassName"></param>
        public static void OwFillDataWithEnum<T>(ListControl ctrl, string resourceClassName)
        {
            var owType = typeof(T);
            var values = Enum.GetValues(owType);
            for (var i = 0; i < values.Length; i++)
            {
                //Localize this for displaying listcontrol's text field.
                var text = OwToStringByCulture(resourceClassName, Enum.Parse(owType, values.GetValue(i).ToString()).ToString());
                //This is for listcontrol's value field
                var key = (Enum.Parse(owType, values.GetValue(i).ToString()));
                //add values of enum to listcontrol.
                ctrl.Items.Add(new ListItem(text, key.ToString()));
            }
        }

        /// <summary>
        /// Get localized strings.
        /// </summary>
        /// <param name="resourceClassName"></param>
        /// <param name="resourceKey"></param>
        /// <returns></returns>
        public static string OwToStringByCulture(string resourceClassName, string resourceKey)
        {
                return (string)HttpContext.GetGlobalResourceObject(resourceClassName, resourceKey);
        }
}
1
répondu BiBongNet 2011-06-26 11:10:48
Enum HowNice {
  [Description("Really Nice")]
  ReallyNice,
  [Description("Kinda Nice")]
  SortOfNice,
  [Description("Not Nice At All")]
  NotNice
}

pour résoudre ce problème, vous devez utiliser une méthode d'extension et un tableau de chaînes comme so:

Enum HowNice {
  ReallyNice  = 0,
  SortOfNice  = 1,
  NotNice     = 2
}

internal static class HowNiceIsThis
{
 const String[] strings = { "Really Nice", "Kinda Nice", "Not Nice At All" }

 public static String DecodeToString(this HowNice howNice)
 {
   return strings[(int)howNice];
 }
}

code Simple et décodage rapide.

1
répondu Sérgio 2012-12-12 14:19:54

j'ai essayé cette approche et ça a marché pour moi.

j'ai créé une classe wrapper pour enums et surchargé l'opérateur implicite pour que je puisse l'affecter aux variables enum (dans mon cas j'ai dû lier un objet à une valeur ComboBox ).

vous pouvez utiliser la réflexion pour formater les valeurs enum de la façon que vous voulez, dans mon cas je récupère le DisplayAttribute hors des valeurs enum (s'il existe).

Espérons que cette aide.

public sealed class EnumItem<T>
{
    T value;

    public override string ToString()
    {
        return Display;
    }

    public string Display { get; private set; }
    public T Value { get; set; }

    public EnumItem(T val)
    {
        value = val;
        Type en = val.GetType();
        MemberInfo res = en.GetMember(val.ToString())?.FirstOrDefault();
        DisplayAttribute display = res.GetCustomAttribute<DisplayAttribute>();
        Display = display != null ? String.Format(display.Name, val) : val.ToString();
    }

    public static implicit operator T(EnumItem<T> val)
    {
        return val.Value;
    }

    public static implicit operator EnumItem<T>(T val)
    {
        return new EnumItem<T>(val);
    }
}

EDIT:

juste au cas où, j'utilise la fonction suivante pour obtenir les valeurs enum que j'utilise pour le DataSource du ComboBox

public static class Utils
{
    public static IEnumerable<EnumItem<T>> GetEnumValues<T>()
    {
        List<EnumItem<T>> result = new List<EnumItem<T>>();
        foreach (T item in Enum.GetValues(typeof(T)))
        {
            result.Add(item);
        }
        return result;
    }
}
1
répondu Ezequiel Moneró Thompson 2017-04-25 01:22:34

une fois que vous avez la méthode GetDescription (elle doit être globale statique), vous pouvez l'utiliser par une méthode d'extension:

public static string ToString(this HowNice self)
{
    return GetDescription<HowNice>(self);
}
0
répondu awe 2011-01-27 12:08:34
Enum HowNice {   
[StringValue("Really Nice")]   
ReallyNice,   
[StringValue("Kinda Nice")]   
SortOfNice,   
[StringValue("Not Nice At All")]   
NotNice 
}

Status = ReallyNice.GetDescription()
0
répondu user1308805 2012-06-30 02:35:44

vous pouvez définir Enum comme

Enum HowNice {   
[StringValue("Really Nice")]   
ReallyNice,   
[StringValue("Kinda Nice")]   
SortOfNice,   
[StringValue("Not Nice At All")]   
NotNice 
} 

et ensuite utiliser HowNice.GetStringValue() .

-1
répondu Vrushal 2011-01-27 10:35:52