2009-10-08 35 views
11

Đây là câu hỏi tương tự với How to bind a custom Enum description to a DataGrid, nhưng trong trường hợp của tôi, tôi có nhiều thuộc tính.Dữ liệu ràng buộc các thuộc tính enum thành lưới và hiển thị mô tả

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

Tôi đang ràng buộc một BindingList <TestResult> đến một WinForms DataGridView (thực sự là một DevExpress.XtraGrid.GridControl, nhưng một giải pháp chung sẽ rộng rãi hơn được áp dụng). Tôi muốn các mô tả xuất hiện chứ không phải là tên enum. Làm thế nào tôi có thể thực hiện điều này? (Không có ràng buộc về lớp/enum/thuộc tính; tôi có thể thay đổi chúng theo ý muốn.)

Trả lời

10

A TypeConverter thường sẽ thực hiện công việc; Dưới đây là một số mã hoạt động cho DataGridView - chỉ cần thêm vào mã của bạn để đọc các mô tả (thông qua phản ánh v.v. - Tôi vừa mới sử dụng tiền tố chuỗi để hiển thị mã tùy chỉnh hoạt động).

Lưu ý bạn có thể cũng muốn ghi đè lên ConvertFrom. Bộ chuyển đổi có thể được chỉ định ở loại hoặc cấp thuộc tính (trong trường hợp bạn chỉ muốn áp dụng cho một số thuộc tính) và cũng có thể được áp dụng khi chạy nếu enum không nằm trong tầm kiểm soát của bạn.

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

Cảm ơn Marc! Kết hợp với EnumHelper của chúng tôi (tương tự như phần đầu tiên của câu trả lời của rally25rs), giải pháp thanh lịch này hoạt động rất đẹp - trong một DataGridView. Thật không may tôi thấy rằng DevExpress.XtraGrid.GridControl không ** không ** phát hiện thuộc tính TypeConverter. Thở dài. Nhưng câu trả lời của bạn rõ ràng là đúng. – TrueWill

+1

... và bạn đã chỉ cho tôi đúng hướng. Tôi thấy rằng Developer Express không có kế hoạch hỗ trợ điều này và cung cấp giải pháp này: http://www.devexpress.com/Support/Center/p/CS2436.aspx – TrueWill

5

Tôi không chắc chắn điều này giúp bao nhiêu, nhưng tôi sử dụng một phương pháp mở rộng trên Enum trông như thế này:

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

Bạn có thể sử dụng một getter tài sản tùy chỉnh trên đối tượng của bạn để trả lại 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(); } } 
} 

Sau đó liên kết lưới của bạn với thuộc tính "RequiredExpectationResultDescr" và "NonRequiredExpectationResultDescr".

Đó có thể là một chút quá phức tạp, nhưng nó là điều 1st tôi đến với :)

+0

+1 để có đề xuất tốt - cảm ơn; chúng tôi có một lớp EnumHelper đã giống như ví dụ của bạn và một nhà phát triển khác đã đề xuất các thuộc tính chuỗi, nhưng tôi lười. ;) – TrueWill

2

Dựa trên hai câu trả lời khác, tôi đã đặt cùng một lớp tổng quát có thể chuyển đổi giữa một enum tùy ý và một chuỗi sử dụng thuộc tính Mô tả trên mỗi giá trị enum.

Điều này sử dụng System.ComponentModel cho định nghĩa của DescriptionAttribute và chỉ hỗ trợ chuyển đổi giữa T và 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); 
    } 
} 
Các vấn đề liên quan