代码之家  ›  专栏  ›  技术社区  ›  TrueWill

将枚举属性绑定到网格和显示说明

  •  11
  • TrueWill  · 技术社区  · 15 年前

    这是一个类似于 How to bind a custom Enum description to a DataGrid ,但在我的例子中,我有多个属性。

    public enum ExpectationResult
    {
        [Description("-")]
        NoExpectation,
    
        [Description("Passed")]
        Pass,
    
        [Description("FAILED")]
        Fail
    }
    
    public class TestResult
    {
        public string TestDescription { get; set; }
        public ExpectationResult RequiredExpectationResult { get; set; }
        public ExpectationResult NonRequiredExpectationResult { get; set; }
    }
    

    我正在将bindingList<testResult>绑定到winforms数据报视图(实际上是devexpress.xtragrid.gridControl,但通用解决方案更适用)。我希望出现描述,而不是枚举名称。我怎样才能做到这一点?(类/枚举/属性没有约束;我可以随意更改它们。)

    3 回复  |  直到 12 年前
        1
  •  10
  •   Marc Gravell    15 年前

    A TypeConverter 通常会做这项工作;这里有一些代码 DataGridView -只需添加代码来阅读描述(通过反射等-我现在刚刚使用了一个字符串前缀来显示自定义代码的工作状态)。

    注意,您可能希望重写 ConvertFrom 也是。可以在类型处指定转换器 属性级别(如果您只希望它应用于某些属性),并且如果枚举不在您的控制之下,也可以在运行时应用。

    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);
        }
    }
    
        2
  •  5
  •   CodingWithSpike    15 年前

    我不确定这有多大帮助,但我对枚举使用了如下扩展方法:

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

    可以在对象上使用自定义属性getter返回名称:

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

    然后将网格绑定到“RequiredExpectationResultDescr”和“UnrequiredExpectationResultDescr”属性。

    这可能有点过于复杂,但我首先想到的是:)

        3
  •  2
  •   Eric J.    14 年前

    基于其他两个答案,我构建了一个类,该类可以使用每个枚举值的描述属性在任意枚举和字符串之间进行一般性转换。

    这将使用System.ComponentModel定义DescriptionAttribute,并且只支持T和字符串之间的转换。

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