এনাম মানগুলির জন্য কাস্টম স্ট্রিং ফর্ম্যাটিংয়ের সাথে আমি এনাম বাউন্ড কম্বোবক্স কীভাবে করব?


135

এনাম টোস্ট্রিং পোস্টে কাস্টম অ্যাট্রিবিউটটি ব্যবহার করার জন্য একটি পদ্ধতি বর্ণনা করা হয়েছে DescriptionAttribute:

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

এবং তারপরে, আপনি GetDescriptionসিন্ট্যাক্স ব্যবহার করে একটি ফাংশন কল করেন :

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

আমি যখন কোনও এনামের মান সহ কোনও কম্বোবক্সকে সহজেই জনবসতি করতে চাইতামGetDescription তবে তা সত্যিই আমাকে সহায়তা করে না , যেহেতু আমি কম্বোবক্সকে কল করতে বাধ্য করতে পারি না

আমি যা চাই তার নিম্নলিখিত প্রয়োজনীয়তা রয়েছে:

  • পড়া (HowNice)myComboBox.selectedItemএনাম মান হিসাবে নির্বাচিত মানটি ফিরিয়ে দেবে।
  • ব্যবহারকারীর পক্ষে ব্যবহারকারী-বান্ধব প্রদর্শন স্ট্রিংগুলি দেখা উচিত, এবং কেবলমাত্র গণনার মানগুলি নয়। সুতরাং " NotNice" দেখার পরিবর্তে , ব্যবহারকারী " Not Nice At All" দেখতে পাবেন ।
  • আশা করি, সমাধানটির জন্য বিদ্যমান গণনাগুলিতে নূন্যতম কোড পরিবর্তন প্রয়োজন হবে।

স্পষ্টতই, আমি যে প্রতিটি এনাম তৈরি করি তার জন্য আমি একটি নতুন শ্রেণি প্রয়োগ করতে এবং এটির ওভাররাইড করতে পারি ToString() , তবে এটি প্রতিটি এনামের জন্য অনেক কাজ এবং আমি তা এড়াতে চাই।

কোন ধারনা?

মুরগি, আমি এমনকি একটি অনুগ্রহ হিসাবে আলিঙ্গন নিক্ষেপ করব :-)


1
jjnguy সঠিক যে জাভা এনামগুলি এটিকে সুন্দরভাবে সমাধান করে ( javahowto.blogspot.com/2006/10/… ), তবে এটি সন্দেহজনক প্রাসঙ্গিকতার।
ম্যাথু ফ্ল্যাশেন

8
জাভা এনামস একটি রসিকতা। হতে পারে তারা 2020 এ সম্পত্তি যুক্ত করবে: /
চাদ গ্রান্ট

হালকা (তবে তর্কযুক্ত কম-শক্তিশালী) সমাধানের জন্য আমার থ্রেডটি দেখুন
গটবলেন্ডার

উত্তর:


42

আপনি এমন একটি টাইপ কনভার্টার লিখতে পারেন যা আপনার সংস্থানগুলিতে সন্ধানের জন্য নির্দিষ্ট বৈশিষ্ট্যগুলি পড়ে। সুতরাং আপনি কোনও ঝামেলা ছাড়াই প্রদর্শনের নামগুলির জন্য বহু ভাষা সমর্থন পাবেন।

TypeConverter এর ConverFrom / ConversTo পদ্ধতিগুলি দেখুন এবং আপনার এনাম ক্ষেত্রগুলিতে বৈশিষ্ট্যগুলি পড়তে প্রতিবিম্বটি ব্যবহার করুন ।


ঠিক আছে, আমি কিছু কোড লিখেছি (এই প্রশ্নের আমার উত্তর দেখুন) - আপনি কি যথেষ্ট মনে করেন, আমি কি কিছু মিস করছি?
শালম ক্রিমার

1
সুন্দর. সর্বোপরি ওভারল, তবে আপনার চলমান চলার জন্য ওভারকিল হতে পারে সফটওয়্যারটির যে কোনও উপায়ে বিশ্বায়িত হবে না global (আমি জানি, এই অনুমানটি পরে মিথ্যা হয়ে উঠবে; ;-))
শিখর

85

ComboBoxআপনার প্রয়োজনীয় সমস্ত কিছু রয়েছে: FormattingEnabledসম্পত্তি, যা আপনার সেট করা উচিত trueএবং Formatইভেন্ট, যেখানে আপনাকে পছন্দসই বিন্যাস যুক্তি স্থাপন করতে হবে। সুতরাং,

myComboBox.FormattingEnabled = true;
myComboBox.Format += delegate(object sender, ListControlConvertEventArgs e)
    {
        e.Value = GetDescription<HowNice>((HowNice)e.Value);
    }

এটি কি কেবল ডেটাবাউন্ড কম্বোবক্সে কাজ করে? অন্যথায় আমি ফর্ম্যাট ইভেন্টটি চালাতে পারি না।
সামথিং

এখানে কেবল সমস্যাটি হ'ল আপনার যুক্তি অনুসারে তালিকাটি সাজানো সম্ভব নয়
গরিলাআপ

এটি একটি দুর্দান্ত সমাধান। DataGridComboBoxColumnযদিও এটি কিছুক্ষণের সাথে কাজ করা দরকার । সমাধান করার কোন সুযোগ? আমি অ্যাক্সেস পেতে একটি উপায় খুঁজে বের করতে পারবেন নই ComboBoxএর DataGridComboBoxColumn
সোকো

46

করবেন না! এনামগুলি ইউআই অবজেক্ট নয়, আদিম - এগুলি ইউআইতে পরিবেশন করে। টোস্ট্রিং () ডিজাইনের দিক থেকে যথেষ্ট খারাপ হবে। আপনি এখানে ভুল সমস্যাটি সমাধান করার চেষ্টা করছেন: আসল সমস্যাটি হল আপনি এনাম.টোস্ট্রিং () কম্বো বাক্সে দেখাতে চান না!

এখন এটি সত্যিই খুব সমাধানযোগ্য সমস্যা! আপনার কম্বো বাক্স আইটেমগুলি উপস্থাপন করার জন্য আপনি একটি ইউআই অবজেক্ট তৈরি করেছেন:

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

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

এবং তারপরে আপনার কম্বো বাক্সের আইটেম সংগ্রহের জন্য এই শ্রেণীর উদাহরণগুলি যুক্ত করুন এবং এই বৈশিষ্ট্যগুলি সেট করুন:

comboBox.ValueMember = "Value";
comboBox.DisplayMember = "Description";

1
আমি আন্তরিকভাবে একমত। উভয়ই আপনার কাছে ToString () এর ফলাফল প্রকাশ করা উচিত নয়। এবং, আপনি স্থানীয়করণ পাবেন না।
vyvind Skaar

আমি জানি এটি পুরানো, তবে কীভাবে এর চেয়ে আলাদা?
nportelli

2
আমি একটি অনুরূপ দেখা করেছি সমাধান যেখানে পরিবর্তে একটি কাস্টম বর্গ ব্যবহারের, তারা একটি করতে enum মান ম্যাপ Dictionaryএবং ব্যবহৃত Keyএবং Valueবৈশিষ্ট্য যেমন DisplayMemberএবং ValueMember
জেফ বি

42

TypeConverter। আমি মনে করি এটিই আমি খুঁজছিলাম। সব শিল শিমেনসন !

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

আমার বর্তমান এনামগুলিতে আমাকে যে পরিবর্তন করতে হবে তা হ'ল তাদের ঘোষণার আগে এই লাইনটি যুক্ত করা।

[TypeConverter(typeof(EnumToStringUsingDescription))]

আমি একবার এটি করার পরে, কোনও এনাম DescriptionAttributeতার ক্ষেত্রগুলির ব্যবহার করে প্রদর্শিত হবে ।

ওহ, এবং TypeConverterএই যেমন সংজ্ঞায়িত করা হবে:

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

এটি আমার কম্বোবক্স কেসটিতে আমাকে সহায়তা করে তবে স্পষ্টতই এটিকে ওভাররাইড করে না ToString()। আমার ধারণা আমি এরই মধ্যে স্থির করব ...


3
আপনি এনাম -> স্ট্রিং পরিচালনা করছেন তবে আপনি যদি সম্পূর্ণ বাস্তবায়ন চান তবে আপনার এনাম> ইনস্ট্যান্সডেস্কিটার এবং স্ট্রিং -> এনুমেরও প্রয়োজন হবে। তবে আমার ধারণা এই মুহূর্তে এটি আপনার প্রয়োজনের জন্য যথেষ্ট display ;)
সিসভে

1
দুর্ভাগ্যক্রমে, যখন আপনার বিবরণ স্থির থাকে তখনই এই সমাধানটি কাজ করে।
লিলি

যাইহোক, টাইপকনভার্টারের ব্যবহার স্থিতিশীল বর্ণনাকুচির সাথে আবদ্ধ নয়, কভার্টার বৈশিষ্ট্যগুলির চেয়ে অন্যান্য উত্স থেকে মানগুলি তৈরি করতে পারে।
দিমিত্রি তাশকিনভ

3
এখন কয়েক ঘন্টা আমার চুল টানছে, তবে এটি এখনও সাধারণ কনসোল অ্যাপ্লিকেশনগুলিতে কাজ করবে বলে মনে হচ্ছে না। আমি এনামটি দিয়ে সাজিয়েছি [TypeConverter(typeof(EnumToStringUsingDescription))] public enum MyEnum {[Description("Blah")] One}, করার চেষ্টা করেছি Console.WriteLine(MyEnum.One)এবং এটি এখনও "ওয়ান" হিসাবে প্রকাশিত হয়েছে। আপনার কি কিছু বিশেষ যাদু দরকার TypeDescriptor.GetConverter(typeof(MyEnum)).ConvertToString(MyEnum.One)(যা ভাল কাজ করে)?
ডেভ

1
@ স্ক্রাইমার আমি আপনার কোড সমর্থনকারী পতাকাগুলির একটি সংস্করণ পোস্ট করেছি। সমস্ত অধিকার আপনার কাছে সংরক্ষিত ...
অভি টার্নার

32

আপনার গণনার উদাহরণ ব্যবহার করে:

using System.ComponentModel;

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

একটি এক্সটেনশন তৈরি করুন:

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

তারপরে আপনি নীচের মতো কিছু ব্যবহার করতে পারেন:

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

আরও তথ্যের জন্য দেখুন: http://www.blackwasp.co.uk/EnumDescription.aspx সমাধানের জন্য ক্রেডিট রিচার্ড কারের কাছে যায়


আমি উল্লিখিত সাইটে বিশদটি অনুসরণ করেছি এবং নীচে এটি ব্যবহার করেছি, আমার জন্য সোজা দেখায় 'স্ট্রিং myDesc = HowNice.ReallyNice.Description ();' মাইডেস্ক আউটপুট দেবে সত্যই
আনন্দ

8

আপনি জেনেরিক স্ট্রাক তৈরি করতে পারেন যা আপনি বর্ণনা করতে পারেন এমন সমস্ত এনামের জন্য ব্যবহার করতে পারেন। ক্লাসে এবং এর থেকে অন্তর্নিহিত রূপান্তরগুলির সাথে, আপনার ভেরিয়েবলগুলি এখনও স্টস্ট্রিং পদ্ধতি ব্যতীত এনামের মতো কাজ করে:

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

}

ব্যবহারের উদাহরণ:

Described<HowNice> nice = HowNice.ReallyNice;

Console.WriteLine(nice == HowNice.ReallyNice); // writes "True"
Console.WriteLine(nice); // writes "Really Nice"

5

আমি মনে করি না আপনি এটি কেবল কোনও ভিন্ন ধরণের সাথে আবদ্ধ না করেই করতে পারেন - কমপক্ষে, সুবিধাজনকভাবে নয়। সাধারণত, আপনি নিয়ন্ত্রণ করতে না পারলেও আপনি কাস্টম ফর্ম্যাট ToString()করতে একটি ব্যবহার করতে পারেন TypeConverter- তবে আইআইআরসি System.ComponentModelস্টাফ এটি এনামদের জন্য সম্মান করে না।

আপনি কোনও string[]বর্ণনার সাথে আবদ্ধ হতে পারেন , বা মূল কী / মান জোড়ার মতো কিছু? (অবচয় / মান) - এরকম কিছু:

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

এবং তারপর আবদ্ধ EnumWrapper<HowNice>.GetValues()


1
'গেটডেস্ক্রিপশন' নামটি বর্তমান প্রসঙ্গে নেই। im .NET 4.0
মুহাম্মদ আদিল জাহিদ

: যে লিঙ্ক পদ থেকে আসে - @MuhammadAdeelZahid প্রশ্ন শুরুতে ঘনিষ্ঠভাবে চেহারা stackoverflow.com/questions/479410/enum-tostring
মার্ক Gravell

দুঃখিত তবে প্রশ্ন থেকে কোনও ক্লু পাওয়া যাচ্ছে না। আপনার পদ্ধতিটি সংকলন করছে না এবং ত্রুটিটি দেখায়।
মুহাম্মদ আদিল জাহিদ

হাই মার্ক, আমি আপনার ধারণা চেষ্টা করেছিলাম। এটি কাজ করছে, তবে এটি নিজের পরিবর্তে theComboBox.SelectItemপ্রকারের । আমার মনে হয় স্ক্রাইমার চায় । EnumWrapper<T>TReading (HowNice)myComboBox.selectedItem will return the selected value as the enum value.
পিটার লি

5

এটি করার সর্বোত্তম উপায়টি একটি ক্লাস তৈরি করা।

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

আমি বিশ্বাস করি যে এটি করার সর্বোত্তম উপায়।

যখন কম্বোবক্সে স্টাফ করা হবে তখন সুন্দর টস্ট্রস্ট্রিং প্রদর্শিত হবে এবং আপনার ক্লাসের কোনও আর কোনও উদাহরণ তৈরি করতে পারে না তা এটিকে মূলত একটি এনাম করে তোলে।

PS সেখানে কিছুটা সিনট্যাক্স ফিক্সও লাগতে পারে, আমি সি # দিয়ে খুব ভাল না। (জাভা লোক)


1
এটি কিভাবে কম্বোবক্স সমস্যার সাথে সহায়তা করে?
peSHIr

ঠিক আছে, এখন, যখন নতুন অবজেক্টটি একটি কম্বোবক্সে স্থাপন করা হবে, তখন এর টসস্ট্রিং সঠিকভাবে প্রদর্শিত হবে এবং ক্লাসটি এখনও এনামের মতো কাজ করে।
jjnguy

1
আমার উত্তরও হয়ে যেত।
মিক্কো রন্তানেন

3
এবং মূল পোস্টারটি কীভাবে স্পষ্টভাবে কোনও ক্লাস চায়নি তা দেখে। আমি মনে করি না যে ক্লাস আরও অনেক বেশি কাজ is আপনি বিবরণটি বিমূর্ত করতে পারেন এবং টোস্ট্রিং সমস্ত এনামের জন্য পিতামাতার ক্লাসে ওভাররাইড করতে পারেন। এর পরে আপনার যা প্রয়োজন তা হ'ল একটি কনস্ট্রাক্টর private HowNice(String desc) : base(desc) { }এবং স্থির ক্ষেত্র।
মিক্কো রন্তানেন

আমি এটি এড়াতে প্রত্যাশা করছিলাম, কারণ এর অর্থ হ'ল আমি যে প্রতিটি গণনা করি তার নিজস্ব বর্গ প্রয়োজন। বিতৃষ্ণা।
শালম ক্রিমার

3

আপনি প্রতিটি এনামের জন্য একটি ক্লাস তৈরি না করে দেওয়ার পরিবর্তে, আমি এনাম মান / প্রদর্শনের পাঠ্যের একটি অভিধান তৈরি করার পরামর্শ দেব এবং পরিবর্তে এটি বাধ্যতামূলক করব।

মনে রাখবেন যে এটির মূল পোস্টে getDescript পদ্ধতি পদ্ধতির উপর নির্ভরতা রয়েছে।

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

চমৎকার ধারণা. তবে আমি কীভাবে এটি একটি কম্বোবক্স দিয়ে ব্যবহার করব? ব্যবহারকারী একবার কম্বোবক্স থেকে একটি আইটেম নির্বাচন করেন, তবে আমি কীভাবে জানতে পারি যে সে কোন আইটেমটি নির্বাচন করেছে? বর্ণনা স্ট্রিং দ্বারা অনুসন্ধান? এটি আমার ত্বকে চুলকানি তোলে ... (বর্ণনা স্ট্রিংগুলির মধ্যে একটি স্ট্রিং "সংঘর্ষ" হতে পারে)
শালম ক্রিমার

নির্বাচিত আইটেমের কীটি হবে আসল এনাম মান। এছাড়াও, বর্ণনামূলক স্ট্রিংগুলিকে সংঘর্ষ করবেন না - ব্যবহারকারী কীভাবে পার্থক্যটি বলবে?
রিচার্ড জাযালে

<কন্টেন্ট> আপনার যদি সংঘর্ষের বর্ণনামূলক স্ট্রিং থাকে তবে আপনার এনামের মানগুলি কোনওভাবেই কম্বোবক্সে আবদ্ধ করা উচিত নয়।
রিচার্ড জাযালে

হুমমম ... আচ্ছা, আপনি কিভাবে আমাকে কম্বোবক্সে আইটেম যুক্ত করবেন তার উদাহরণ কোড দিতে পারেন? আমি যা ভাবতে পারি তা হ'ল "foreach (বর্ণনাগুলিতে স্ট্রিংস ডিক্ট.ভ্যালুগুলি) {this.combobox.Items.Add (গুলি);}"
শালম ক্রিমার

1
কম্বোবক্স.ডাটাসোর্স = অভিধান;
রিচার্ড জাযালে

3

C # তে এনামগুলির টোস্ট্রিং () ওভাররাইড করা সম্ভব নয়। তবে আপনি এক্সটেনশন পদ্ধতিগুলি ব্যবহার করতে পারেন;

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

অবশ্যই আপনাকে পদ্ধতিটিতে একটি স্পষ্ট কল করতে হবে, অর্থাত্;

HowNice.ReallyNice.ToString(0)

এটি একটি স্যুইচ স্টেটমেন্ট এবং সমস্ত সহ একটি দুর্দান্ত সমাধান নয় - তবে এটি কাজ করা উচিত এবং আশা করা যায় যে অনেকগুলি পুনরায় লেখার জন্য সাদা করা ...


সচেতন থাকুন যে নিয়ন্ত্রণটি আপনার এনামের সাথে আবদ্ধ হয় সেগুলি এই এক্সটেনশন পদ্ধতিটিকে কল করবে না, এটি ডিফল্ট বাস্তবায়নকে কল করবে।
রিচার্ড জাযালে

ঠিক। সুতরাং এটি একটি কার্যকর বিকল্প যদি আপনার কোথাও কোনও বিবরণ প্রয়োজন হয় তবে এটি পোজযুক্ত কম্বোবক্স সমস্যায় সহায়তা করে না।
peSHIr

একটি বড় সমস্যা হ'ল এটিকে কখনই ডাকা হবে না (এক্সটেনশন পদ্ধতি হিসাবে) - ইতিমধ্যে বিদ্যমান উদাহরণগুলি সর্বদা অগ্রাধিকার গ্রহণ করে।
মার্ক Gravell

অবশ্যই মার্ক ঠিক (যথারীতি?) আমার .NET অভিজ্ঞতাটি ন্যূনতম, তবে পদ্ধতিটিতে একটি ডামি প্যারামিটার সরবরাহ করা কৌশলটি করা উচিত। সম্পাদিত উত্তর।
Björn

2

@ স্ক্রাইমারের উত্তর অনুসরণ করে, এখানে এনাম-টু-স্ট্রিং টাইপের রূপান্তরকারীটির একটি সংস্করণ রয়েছে, যা পতাকাগুলিকেও সমর্থন করে:

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

}

এবং এটি ব্যবহারের জন্য একটি এক্সটেনশন পদ্ধতি:

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

1

আমি যে কোনও ধরণের সাথে ব্যবহারের জন্য জেনেরিক ক্লাস লিখি। আমি অতীতে এরকম কিছু ব্যবহার করেছি:

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
}

এর উপরে, আপনি এনাম টাইপযুক্ত কম্বোবক্স আইটেমগুলির একটি তালিকা তৈরি করতে একটি স্থিতিশীল "ফ্যাক্টরি পদ্ধতি" যুক্ত করতে পারেন (আপনি সেখানে থাকা গেটডেস্ক্রিপশন পদ্ধতির মতোই)। এটি আপনাকে প্রতি এনাম টাইপ অনুযায়ী একটি সত্তা বাস্তবায়িত করতে বাঁচাতে পারে এবং "গেটডেস্ক্রিপশনস" সহায়ক পদ্ধতিটির জন্য একটি ব্যক্তিগত / লজিক্যাল জায়গা সরবরাহ করবে (ব্যক্তিগতভাবে আমি এটিকে ফ্রিএনম (টিজ অব) বলব ...


1

আপনার যা প্রয়োজন Valueতা HowNiceসমেত একটি সংগ্রহ তৈরি করুন (যেমন এনাম মান সম্বলিত একটি সম্পত্তি এবং একটি Descriptionসম্পত্তি সম্বলিত সাধারণ সামগ্রীGetDescription<HowNice>(Value) এবং databind যে সংগ্রহে কম্বো।

এর মতো বিট:

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

আপনার যখন সংগ্রহ ক্লাস থাকে তখন:

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

}

যেমন আপনি দেখতে পাচ্ছেন, আপনার গণকের একটি সাবসেট নির্বাচন করতে এবং / অথবা আপনি উল্লিখিত ফাংশনটি stringব্যবহার না করে একটি কাস্টম বিন্যাস প্রয়োগ করতে এই সংগ্রহটি সহজেই কাস্টমাইজযোগ্য GetDescription<T>(x)


দুর্দান্ত, তবে আমি এমন কিছু সন্ধান করছি যা কোডে আরও কম কাজের প্রয়োজন।
শালম ক্রিমার

এমনকি আপনি যদি আপনার সমস্ত গণনাকারীর জন্য এই জাতীয় জিনিসের জন্য একই জেনেরিক সংগ্রহটি ব্যবহার করতে পারেন? আমি অবশ্যই প্রতিটি এনামের জন্য এই জাতীয় সংকলন লেখার পরামর্শ দিচ্ছিলাম না।
পিএসআইআইআর

1

আপনি Enum.ToString টার্গেট করতে পোস্টশার্প ব্যবহার করতে এবং আপনার পছন্দসই অ্যাডিশনাল কোড যুক্ত করতে পারেন। এর জন্য কোনও কোড পরিবর্তন দরকার হয় না।


1

আপনার যা দরকার তা হ'ল একটি এনামকে কেবল পঠনযোগ্য সংগ্রহের মধ্যে পরিণত করা এবং সংগ্রহটি কম্বোবক্সের সাথে আবদ্ধ করা (বা কোনও কী-মান জোড় সক্ষম করার জন্য এটি নিয়ন্ত্রণের জন্য নিয়ন্ত্রণ)

প্রথমে আপনার তালিকার আইটেমগুলি রাখতে একটি শ্রেণি প্রয়োজন। যেহেতু আপনার যা দরকার তা হ'ল ইন / স্ট্রিং জুড়িটি আমি একটি ইন্টারফেস এবং বেস ক্লাস কম্বো ব্যবহার করার পরামর্শ দিচ্ছি যাতে আপনি যে কোনও বস্তুতে কার্যকারিতা কার্যকর করতে পারেন:

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
}

এখানে ইন্টারফেস এবং একটি নমুনা শ্রেণি রয়েছে যা এটি প্রয়োগ করে N 'এন ক্লাসটি' ক্লাসটি কী দৃ strongly়ভাবে টাইপ করা হয়েছে এবং আইভালিউডেস্ক্রিটেশন আইটেম প্রোপার্টিগুলি স্পষ্টভাবে প্রয়োগ করা হয়েছে (যাতে শ্রেণীর যা কিছু বৈশিষ্ট্য থাকতে পারে এবং আপনি যেগুলি প্রয়োগ করেন তা বেছে নিতে পারেন) কী / মান জোড়।

এখন EnumToReadOnly সংগ্রহ সংগ্রহ শ্রেণি:

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

}

সুতরাং আপনার কোডে আপনার যা প্রয়োজন তা হ'ল:

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

মনে রাখবেন যে আপনার সংগ্রহটি মাই আইটেমের সাথে টাইপ করা হয়েছে তাই আপনি যদি উপযুক্ত মালিককে বাঁধেন তবে কম্বোবক্স মানটি একটি এনাম মানটি ফিরিয়ে আনতে হবে।

আমি সংগ্রহটি সাধারণ কম্বোকে গ্রাহ্যযোগ্য তুলনায় আরও বেশি উপযোগী করে তুলতে টি [এই এনাম টি] সম্পত্তি যুক্ত করেছি, উদাহরণস্বরূপ পাঠ্যবক্স 1 1 পাঠ্য = এনামকোল [হাউনাইস.আরলাইনাইস] Nনিসনেসডেস্ক্রিপশন;

আপনি অবশ্যই এই আইফর্মটির জন্য মাই আইটেমকে কী / মান শ্রেণিতে রূপান্তর করতে বেছে নিতে পারেন কার্যকরভাবে মাই আইটেমকে পুরোপুরি এনামটোররেডলি কলিকেশন টাইপের আর্গুমেন্টে এড়িয়ে যেতে পারে তবে আপনি কীটির জন্য অন্তর্নিহিত যেতে বাধ্য হবেন (যার অর্থ কম্বোবক্স 1 হবে। এনএম টাইপ না করে ইনট ফিরে আসবে)। আপনি তার আশেপাশে কাজ করেন যদি আপনি মাই আইটেম প্রতিস্থাপনের জন্য একটি কীভ্যালিউআইটেম ক্লাস তৈরি করেন এবং আরও অনেক কিছু ...


1

এই পুরানো থ্রেড আপ করার জন্য দুঃখিত।

আমি এনামকে স্থানীয়করণের জন্য নিম্নলিখিত পদ্ধতিতে যাব, কারণ এটি উদাহরণস্বরূপ একটি ড্রপডাউনলিস্ট পাঠ্য ক্ষেত্রের মাধ্যমে কেবল বর্ণন নয়, ব্যবহারকারীর কাছে অর্থবহ এবং স্থানীয়ীকৃত মানগুলি প্রদর্শন করতে পারে।

প্রথমত, আমি বিশ্বব্যাপী সংস্থান ফাইল থেকে স্থানীয়করণের স্ট্রিংগুলি পাওয়ার জন্য ওউটোস্ট্রিংবাইকালচার নামে একটি সাধারণ পদ্ধতি তৈরি করি, উদাহরণস্বরূপ এটি অ্যাপ_গ্লোবাল রিসোর্স ফোল্ডারে বাইবং নেট.রেসেক্স। এই রিসোর্স ফাইলের ভিতরে, নিশ্চিত হয়ে নিন যে আপনার কাছে সমস্ত স্ট্রিং এনামের মানগুলির মতোই রয়েছে (ReallyNice, SortOfNice, NotNice)। এই পদ্ধতিতে, আমি প্যারামিটারটিতে পাস করি: রিসোর্স ক্লাসনাম যা সাধারণত রিসোর্স ফাইলের নাম।

এরপরে, এনওমকে এটির ডেটাসোর্স হিসাবে একটি ড্রপডাউনলিস্ট পূরণ করার জন্য আমি একটি স্ট্যাটিক পদ্ধতি তৈরি করি, যার নাম OwFillDataWithEnum। এই পদ্ধতিটি পরে কোনও এনামের সাথে ব্যবহার করা যেতে পারে।

তারপরে ড্রপডাউনলিস্ট 1 নামে একটি ড্রপডাউনলিস্ট সহ পৃষ্ঠাতে, আমি ড্রপডাউনলিস্টে এনামটি পূরণ করার জন্য নীচের মাত্র একটি সাধারণ লাইন কোড_পেজটি লোড করুন।

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

এটাই. আমি মনে করি এর মতো কয়েকটি সাধারণ পদ্ধতিতে, আপনি কোনও এনামের সাথে যে কোনও তালিকা নিয়ন্ত্রণ পূরণ করতে পারেন, কেবল বর্ণনামূলক মান নয়, স্থানীয় পাঠ্য প্রদর্শন করতে। আপনি আরও ভাল ব্যবহারের জন্য এক্সটেনশন পদ্ধতি হিসাবে এই সমস্ত পদ্ধতি তৈরি করতে পারেন।

এই সাহায্য আশা করি। ভাগ করে নিতে শেয়ার করুন!

পদ্ধতিগুলি এখানে:

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
Enum HowNice {
  [Description("Really Nice")]
  ReallyNice,
  [Description("Kinda Nice")]
  SortOfNice,
  [Description("Not Nice At All")]
  NotNice
}

এটি সমাধান করার জন্য আপনার পছন্দসই পদ্ধতি এবং এর মতো স্ট্রিংয়ের অ্যারে ব্যবহার করা উচিত:

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

সাধারণ কোড এবং দ্রুত ডিকোডিং।


স্ট্রিং ভেরিয়েবলটি স্ট্যাটিক হওয়া উচিত এবং এর মতো ঘোষিত হওয়া উচিত: স্ট্যাটিক স্ট্রিং [] স্ট্রিংস = নতুন [] {...}
সেরজিও

এটির সাথে একমাত্র সমস্যাটি হ'ল আপনার প্রত্যেকটি গণনার জন্য আপনার একটি ফাংশন থাকা দরকার এবং বিবরণটি গণনা ছাড়া পৃথক হবে ...
অ্যাভি টার্নার

1

আমি এই পদ্ধতির চেষ্টা করেছি এবং এটি আমার পক্ষে কাজ করেছে।

আমি এনামগুলির জন্য একটি মোড়কের ক্লাস তৈরি করেছি এবং অন্তর্ভুক্ত অপারেটরটিকে ওভারলোড করেছি যাতে আমি এটি এনাম ভেরিয়েবলগুলিতে অর্পণ করতে পারি (আমার ক্ষেত্রে আমার কোনও বস্তুর একটি ComboBoxমানকে বাঁধতে হয়েছিল )।

আপনি যেভাবে এনাম মানগুলি চান তা ফর্ম্যাট করতে আপনি প্রতিবিম্বটি ব্যবহার করতে পারেন, আমার ক্ষেত্রে আমি DisplayAttributeএনাম মানগুলি (যদি বিদ্যমান থাকে) থেকে বের করে আনতে পারি ।

আশাকরি এটা সাহায্য করবে.

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

সম্পাদনা করুন:

শুধু ক্ষেত্রে, আমি পেতে নিম্নলিখিত ফাংশন ব্যবহার enumযে আমি জন্য ব্যবহার মান DataSourceএর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;
    }
}

0

আপনার কাছে একবার GetDescriptionপদ্ধতিটি (এটি বিশ্বব্যাপী স্ট্যাটিক হওয়া দরকার) হয়ে গেলে আপনি এটি কোনও এক্সটেনশন পদ্ধতির মাধ্যমে ব্যবহার করতে পারেন:

public static string ToString(this HowNice self)
{
    return GetDescription<HowNice>(self);
}

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

Status = ReallyNice.GetDescription()

3
স্ট্যাকওভারফ্লোতে স্বাগতম! পোস্টের নির্ভুলতার উন্নতির জন্য একটি নমুনা কোডের জন্য একটি সংক্ষিপ্ত বিবরণ প্রদান করা সর্বদা ভাল :)
Picrofo সফ্টওয়্যার

-1

আপনি Enum হিসাবে সংজ্ঞায়িত করতে পারেন

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

এবং তারপরে ব্যবহার করুন HowNice.GetStringValue()


2
এটি সংকলন করে না (আমার কাছে নেট 3.5 আছে)। Ringস্ট্রিংভ্যালু´ কোথায় ঘোষণা করা হয়েছে?
বিস্মিত

1
@ স্ক্রাইমারের উত্তর একই, তিনি ফ্রেমওয়ার্কের বাইরে কোনও বৈশিষ্ট্য ব্যবহার করছেন, তবে আপনি একরকম স্ব-সংজ্ঞায়িত বৈশিষ্ট্য ব্যবহার করেন।
অলিভার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.