【问题标题】:Data bind enum properties to grid and display description数据将枚举属性绑定到网格并显示描述
【发布时间】:2010-12-05 03:15:33
【问题描述】:

这是与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 绑定到 WinForms DataGridView(实际上是 DevExpress.XtraGrid.GridControl,但通用解决方案将更广泛适用)。我希望出现描述而不是枚举名称。我怎样才能做到这一点? (对类/枚举/属性没有限制;我可以随意更改它们。)

【问题讨论】:

    标签: c# winforms data-binding datagridview enums


    【解决方案1】:

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

    【讨论】:

    • 谢谢马克!结合我们的 EnumHelper(类似于 rally25rs 答案的第一部分),这个优雅的解决方案在 DataGridView 中运行良好。不幸的是,我发现 DevExpress.XtraGrid.GridControl 确实 not 检测到 TypeConverter 属性。叹。但你的答案显然是正确的。
    • ...您为我指明了正确的方向。我发现 Developer Express 不打算支持此功能,并提供此解决方法:devexpress.com/Support/Center/p/CS2436.aspx
    【解决方案2】:

    我不确定这有多大帮助,但我在 Enum 上使用了一个扩展方法,如下所示:

        /// <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”和“NonRequiredExpectationResultDescr”属性。

    这可能有点过于复杂,但这是我想出的第一件事:)

    【讨论】:

    • +1 的好建议 - 谢谢;我们已经有一个 EnumHelper 类,就像您的示例一样,另一个开发人员建议使用字符串属性,但我很懒。 ;)
    【解决方案3】:

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

    这里使用System.ComponentModel来定义DescriptionAttribute,只支持T和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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-12-18
      • 1970-01-01
      • 2018-11-19
      • 2011-10-18
      • 2015-10-09
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多