Jak mam combobox związany z enum z niestandardowym formatowaniem ciągów dla wartości enum?

W poście Enum ToString opisano metodę, która używa atrybutu custom DescriptionAttribute w następujący sposób:

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

A następnie wywołujesz funkcję GetDescription, używając składni takiej jak:

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

Ale To mi nie pomaga kiedy chcę po prostu wypełnić ComboBox wartościami enum, ponieważ nie mogę zmusić ComboBox do wywołania GetDescription.

To, czego chcę, ma następujące wymagania:

  • odczyt (HowNice)myComboBox.selectedItem zwróci wybraną wartość jako wartość enum.
  • Użytkownik powinien widzieć przyjazne dla użytkownika ciągi wyświetlania, a nie tylko nazwę wartości wyliczenia. Zamiast więc zobaczyć "NotNice", użytkownik zobaczy "Not Nice At All".
  • miejmy nadzieję, że rozwiązanie będzie wymagało minimalnych zmian w kodzie istniejących wyliczeń.

Oczywiście, mógłbym zaimplementować nową klasę dla każdego enum, które tworzę, i nadpisać jej ToString(), ale to dużo pracy dla każdego enum, i wolałbym tego uniknąć.

Any pomysły?

Heck, dorzucę nawet uścisk jako nagrodę: -)

Author: Community, 2009-04-28

21 answers

Możesz napisać TypeConverter, który odczytuje określone atrybuty, aby wyszukać je w swoich Zasobach. W ten sposób można uzyskać obsługę wielu języków dla wyświetlania nazw bez większych kłopotów.

Spójrz na metody Convertfrom/ConvertTo Typeconvertera i użyj reflection, aby odczytać atrybuty na polach enum .

 41
Author: sisve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-27 08:27:29

ComboBox zawiera wszystko, czego potrzebujesz: właściwość FormattingEnabled, którą powinieneś ustawić na true oraz Zdarzenie Format, w którym musisz umieścić żądaną logikę formatowania. Zatem

myComboBox.FormattingEnabled = true;
myComboBox.Format += delegate(object sender, ListControlConvertEventArgs e)
    {
        e.Value = GetDescription<HowNice>((HowNice)e.Value);
    }
 85
Author: Anton Gogolev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:36:31

Nie! Liczby są prymitywami, a nie obiektami interfejsu użytkownika - dzięki czemu służą do interfejsu użytkownika .ToString () byłoby całkiem złe z punktu widzenia projektu. Próbujesz rozwiązać niewłaściwy problem: prawdziwym problemem jest to, że nie chcesz Enum.ToString (), aby pojawić się w polu combo!

[2]}Teraz jest to naprawdę bardzo rozwiązywalny problem! Tworzysz obiekt interfejsu użytkownika, który będzie reprezentował twoje elementy pola kombi:
sealed class NicenessComboBoxItem
{
    public string Description { get { return ...; } }
    public HowNice Value { get; private set; }

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

A następnie po prostu dodaj instancje tej klasy do kolekcji przedmiotów twojego combo box i ustaw te właściwości:

comboBox.ValueMember = "Value";
comboBox.DisplayMember = "Description";
 44
Author: Sander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:33:25

TypeConverter. Myślę, że tego właśnie szukałem. Niech żyje Simon Svensson!

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

Wszystko, co muszę zmienić w moim obecnym enum, to dodać tę linię przed ich deklaracją.

[TypeConverter(typeof(EnumToStringUsingDescription))]

Gdy to zrobię, każde enum zostanie wyświetlone za pomocą DescriptionAttribute jego pól.

Oh, A TypeConverter byłoby zdefiniowane tak:

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

To pomaga mi w sprawie Comboboxu, ale oczywiście nie zastępuje ToString(). Chyba zadowoli mnie to. tymczasem...

 40
Author: Shalom Craimer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:53

Używając przykładu wyliczenia:

using System.ComponentModel;

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

Utwórz rozszerzenie:

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

Wtedy możesz użyć czegoś takiego:

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

Zobacz: http://www.blackwasp.co.uk/EnumDescription.aspx aby uzyskać więcej informacji. Kredyt idzie do Richrd Carr za rozwiązanie

 30
Author: Tyler Durden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-01 01:45:58

Możesz stworzyć strukturę generyczną, której możesz użyć dla wszystkich Twoich enum zawierających opisy. Z domyślnymi konwersjami do i z klasy, Twoje zmienne nadal działają jak enum, z wyjątkiem metody 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;
    }

}

Przykład użycia:

Described<HowNice> nice = HowNice.ReallyNice;

Console.WriteLine(nice == HowNice.ReallyNice); // writes "True"
Console.WriteLine(nice); // writes "Really Nice"
 8
Author: Guffa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 08:00:16

Nie sądzę, że można to zrobić bez po prostu związania się z innym typem - przynajmniej, nie wygodnie. Zwykle, nawet jeśli nie możesz kontrolować ToString(), możesz użyć TypeConverter do niestandardowego formatowania - ale IIRC rzeczy System.ComponentModel nie respektują tego dla enum.

Można powiązać z string[] opisów, lub coś zasadniczo jak para klucz / wartość? (description/value) - coś w stylu:

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

A następnie związać do EnumWrapper<HowNice>.GetValues()

 5
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:43:59

Najlepszym sposobem na to jest zrobienie klasy.

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!");
}
Uważam, że to najlepszy sposób.

Po załadowaniu do comboboxów zostanie pokazany pretty ToString, a fakt, że nikt nie może zrobić więcej instancji twojej klasy zasadniczo czyni go enum.

P. s. mogą być jakieś drobne poprawki składni, nie jestem zbyt dobry w C#. (Java guy)

 5
Author: jjnguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-20 00:11:59

Biorąc pod uwagę, że nie chcesz tworzyć klasy dla każdego enum, zalecam utworzenie słownika wartości enum/wyświetl tekst i powiązanie go zamiast tego.

Zauważ, że jest to zależne od metod metody GetDescription w oryginalnym poście.

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
Author: Richard Szalay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:36:06

Nie jest możliwe nadpisanie ToString () enums w C#. Można jednak użyć metod rozszerzenia;

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

Oczywiście będziesz musiał wykonać wyraźne wywołanie metody, tj.]}

HowNice.ReallyNice.ToString(0)

To nie jest dobre rozwiązanie, z instrukcją switch i w ogóle - ale powinno działać i mam nadzieję, że wiele przeróbek...

 3
Author: Björn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:39:53

Po odpowiedzi @ scramer, oto wersja konwertera typu enum-to-string, który obsługuje również flagi:

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

}

I metoda rozszerzenia jej użycia:

    /// <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
Author: Avi Turner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-10 07:34:46

Napisałbym klasę generyczną do użycia z dowolnym typem. Kiedyś używałem czegoś takiego:

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
}

Poza tym, możesz dodać statyczną "metodę fabryczną", aby utworzyć listę elementów combobox z podanym typem enum (prawie tak samo jak metoda GetDescriptions, którą tam posiadasz). Oszczędziłoby to konieczności implementacji jednego encji dla każdego typu enum, a także zapewniłoby ładne / logiczne miejsce dla metody pomocniczej "GetDescriptions" (osobiście nazwałbym ją FromEnum(T obj) ...

 1
Author: Dan C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 07:53:15

Utwórz kolekcję, która zawiera to, czego potrzebujesz (np. proste obiekty zawierające właściwość Value zawierającą wartość HowNice enum oraz właściwość Description zawierającą GetDescription<HowNice>(Value) i znajdź kombinację do tej kolekcji.

Trochę tak:

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

Gdy masz klasę kolekcji taką jak ta:

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

}

Jak widać, ta kolekcja jest łatwo konfigurowalna za pomocą lambda ' s, aby wybrać podzbiór wyliczenia i/lub zaimplementować niestandardowe formatowanie do string zamiast używać GetDescription<T>(x) funkcja, o której wspominasz.

 1
Author: peSHIr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 08:13:19

Możesz użyć PostSharp do celu Enum.ToString i dodaj dodatkowy kod, który chcesz. Nie wymaga to żadnych zmian w kodzie.

 1
Author: majkinetor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 08:59:59

To, czego potrzebujesz, to zamienić enum w ReadonlyCollection i powiązać kolekcję z comboboxem (lub dowolną kontrolką z włączoną parą klucz-wartość)

Po pierwsze, potrzebujesz klasy, która zawierałaby elementy listy. Ponieważ wszystko, czego potrzebujesz, to para int/string, sugeruję użycie interfejsu i kombinacji klas bazowych, aby móc zaimplementować funkcjonalność w dowolnym obiekcie:

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
}

Oto interfejs i przykładowa klasa, która go implementuje.Zauważ, że Klasa" Klucz jest silnie wpisany do Enum, i że proprties IValueDescritionItem są zaimplementowane w sposób jasny (więc klasa może mieć dowolne właściwości i możesz wybrać te, które implementują parę klucz / wartość.

Klasa 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)];
        }
    }

}

Więc wszystko czego potrzebujesz w swoim kodzie to:

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

Pamiętaj, że Twoja kolekcja jest wpisywana za pomocą myitem, więc wartość combobox powinna zwracać wartość enum, jeśli powiązasz ją z odpowiednią proprtie.

Dodałem właściwość t this[Enum t] sprawia, że kolekcja jest jeszcze bardziej użyteczna niż zwykłe combo, na przykład textBox1.Tekst = "urodził się polski malarz i rysownik",ReallyNice].NicenessDescription;

Możesz oczywiście zmienić MyItem w klasę klucza / wartości używaną tylko dla tego puprose skutecznie pomijając MyItem w argumentach typu EnumToReadnlyCollection, ale wtedy będziesz zmuszony przejść do int dla klucza (co oznacza uzyskanie combobox1.SelectedValue zwróci int, a nie enum Typ). Obejdziesz to, jeśli stworzysz klasę KeyValueItem, która zastąpi MyItem i tak dalej i tak dalej...

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-25 14:36:27

Przepraszam za ten stary wątek.

Wybrałbym następujący sposób lokalizacji enum, ponieważ może wyświetlać użytkownikowi znaczące i zlokalizowane wartości, a nie tylko opis, poprzez pole tekstowe dropdownlist w tym przykładzie.

Najpierw stworzyłem prostą metodę o nazwie OwToStringByCulture, aby uzyskać zlokalizowane ciągi znaków z globalnego pliku zasobów, w tym przykładzie jest to BiBongNet.resx w folderze App_GlobalResources. W tym pliku zasobów upewnij się, że wszystkie ciągi są takie same jako wartości enum (ReallyNice, SortOfNice, NotNice). W tej metodzie przekazuję parametr: resourceClassName, który jest zwykle nazwą pliku zasobu.

Następnie tworzę statyczną metodę wypełniania listy dropdownlist za pomocą enum jako źródła danych o nazwie OwFillDataWithEnum. Metoda ta może być używana z dowolnym enum później.

Następnie na stronie z dropdownlist o nazwie DropDownList1, ustawiłem w Page_Load następujący tylko jeden prosty wiersz kodu, aby wypełnić enum do dropdownlist.

 BiBongNet.OwFillDataWithEnum<HowNice>(DropDownList1, "BiBongNet");
To wszystko. Myślę, że za pomocą kilku prostych metod, takich jak te, możesz wypełnić dowolną kontrolę listy dowolnym enum, nie tylko wartościami opisowymi, ale zlokalizowanym tekstem do wyświetlenia. Możesz zrobić wszystkie te metody jako metody rozszerzenia dla lepszego użycia. Mam nadzieję, że to pomoże. Podziel się, aby się podzielić!

Oto metody:

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
Author: BiBongNet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-26 11:10:48
Enum HowNice {
  [Description("Really Nice")]
  ReallyNice,
  [Description("Kinda Nice")]
  SortOfNice,
  [Description("Not Nice At All")]
  NotNice
}

Aby rozwiązać ten problem należy użyć metody rozszerzenia i tablicy łańcuchów takich jak TAK:

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

Prosty kod i szybkie dekodowanie.

 1
Author: Sérgio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-12 14:19:54

Próbowałem tego podejścia i zadziałało na mnie.

Stworzyłem klasę wrapper dla enum i przeciąłem Operator implicit, aby móc przypisać go do zmiennych enum (w moim przypadku musiałem powiązać obiekt z wartością ComboBox).

Możesz użyć reflection, aby sformatować wartości enum tak, jak chcesz, w moim przypadku pobieram DisplayAttribute z wartości enum (jeśli istnieją).

Mam nadzieję, że to pomoże.
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:

Na wszelki wypadek, używam następujących funkcja, aby uzyskać enum wartości, których używam dla {[5] } z 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
Author: Ezequiel Moneró Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 01:22:34

Gdy masz metodę GetDescription (musi ona być globalna statyczna), możesz użyć jej za pomocą metody rozszerzenia:

public static string ToString(this HowNice self)
{
    return GetDescription<HowNice>(self);
}
 0
Author: awe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: user1308805,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-30 02:35:44

Możesz zdefiniować Enum jako

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

A następnie użyć HowNice.GetStringValue().

 -1
Author: Vrushal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-27 10:35:52