Data bind enum properties to grid and display description

前端 未结 3 1308
挽巷
挽巷 2020-12-14 04:34

This is a similar question to How to bind a custom Enum description to a DataGrid, but in my case I have multiple properties.

public enum ExpectationResult
{         


        
相关标签:
3条回答
  • 2020-12-14 05:01

    A TypeConverter will usually do the job; here's some code that works for DataGridView - just add in your code to read the descriptions (via reflection etc - I've just used a string prefix for now to show the custom code working).

    Note you would probably want to override ConvertFrom too. The converter can be specified at the type or the property level (in case you only want it to apply for some properties), and can also be applied at runtime if the enum isn't under your control.

    using System.ComponentModel;
    using System.Windows.Forms;
    [TypeConverter(typeof(ExpectationResultConverter))]
    public enum ExpectationResult
    {
        [Description("-")]
        NoExpectation,
    
        [Description("Passed")]
        Pass,
    
        [Description("FAILED")]
        Fail
    }
    
    class ExpectationResultConverter : EnumConverter
    {
        public ExpectationResultConverter()
            : base(
                typeof(ExpectationResult))
        { }
    
        public override object ConvertTo(ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, object value,
            System.Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return "abc " + value.ToString(); // your code here
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
    
    public class TestResult
    {
        public string TestDescription { get; set; }
        public ExpectationResult RequiredExpectationResult { get; set; }
        public ExpectationResult NonRequiredExpectationResult { get; set; }
    
        static void Main()
        {
            BindingList<TestResult> list = new BindingList<TestResult>();
            DataGridView grid = new DataGridView();
            grid.DataSource = list;
            Form form = new Form();
            grid.Dock = DockStyle.Fill;
            form.Controls.Add(grid);
            Application.Run(form);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 05:10

    Based on the two other answers, I have put together a class that can generically convert between an arbitrary enum and a string using a Description attribute on each enum value.

    This uses System.ComponentModel for the definition of DescriptionAttribute, and only supports conversion between T and String.

    public class EnumDescriptionConverter<T> : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return (sourceType == typeof(T) || sourceType == typeof(string));
        }
    
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return (destinationType == typeof(T) || destinationType == typeof(string));
        }
    
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            Type typeFrom = context.Instance.GetType();
    
            if (typeFrom == typeof(string))
            {
                return (object)GetValue((string)context.Instance);
            }
            else if (typeFrom is T)
            {
                return (object)GetDescription((T)context.Instance);
            }
            else
            {
                throw new ArgumentException("Type converting from not supported: " + typeFrom.FullName);
            }
        }
    
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            Type typeFrom = value.GetType();
    
            if (typeFrom == typeof(string) && destinationType == typeof(T))
            {
                return (object)GetValue((string)value);
            }
            else if (typeFrom == typeof(T) && destinationType == typeof(string))
            {
                return (object)GetDescription((T)value);
            }
            else
            {
                throw new ArgumentException("Type converting from not supported: " + typeFrom.FullName);
            }
        }
    
        public string GetDescription(T en)
        {
            var type = en.GetType();
            var memInfo = type.GetMember(en.ToString());
    
            if (memInfo != null && memInfo.Length > 0)
            {
                var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs != null && attrs.Length > 0)
                    return ((DescriptionAttribute)attrs[0]).Description;
            }
            return en.ToString();
        }
    
        public T GetValue(string description)
        {
            foreach (T val in Enum.GetValues(typeof(T)))
            {
                string currDescription = GetDescription(val);
                if (currDescription == description)
                {
                    return val;
                }
            }
    
            throw new ArgumentOutOfRangeException("description", "Argument description must match a Description attribute on an enum value of " + typeof(T).FullName);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 05:16

    I'm not sure how much this helps, but I use an extension method on Enum that looks like this:

        /// <summary>
        /// Returns the value of the description attribute attached to an enum value.
        /// </summary>
        /// <param name="en"></param>
        /// <returns>The text from the System.ComponentModel.DescriptionAttribute associated with the enumeration value.</returns>
        /// <remarks>
        /// To use this, create an enum and mark its members with a [Description("My Descr")] attribute.
        /// Then when you call this extension method, you will receive "My Descr".
        /// </remarks>
        /// <example><code>
        /// enum MyEnum {
        ///     [Description("Some Descriptive Text")]
        ///     EnumVal1,
        ///
        ///     [Description("Some More Descriptive Text")]
        ///     EnumVal2
        /// }
        /// 
        /// static void Main(string[] args) {
        ///     Console.PrintLine( MyEnum.EnumVal1.GetDescription() );
        /// }
        /// </code>
        /// 
        /// This will result in the output "Some Descriptive Text".
        /// </example>
        public static string GetDescription(this Enum en)
        {
            var type = en.GetType();
            var memInfo = type.GetMember(en.ToString());
    
            if (memInfo != null && memInfo.Length > 0)
            {
                var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs != null && attrs.Length > 0)
                    return ((DescriptionAttribute)attrs[0]).Description;
            }
            return en.ToString();
        }
    

    You could use a custom property getter on your object to return the name:

    public class TestResult
    {
        public string TestDescription { get; set; }
        public ExpectationResult RequiredExpectationResult { get; set; }
        public ExpectationResult NonRequiredExpectationResult { get; set; }
    
        /* *** added these new property getters *** */
        public string RequiredExpectationResultDescr { get { return this.RequiredExpectationResult.GetDescription(); } }
        public string NonRequiredExpectationResultDescr { get { return this.NonRequiredExpectationResult.GetDescription(); } }
    }
    

    Then bind your grid to the "RequiredExpectationResultDescr" and "NonRequiredExpectationResultDescr" properties.

    That might be a little over-complicated, but its the 1st thing I came up with :)

    0 讨论(0)
提交回复
热议问题