2009-10-08 68 views
11

這是一個類似的問題How to bind a custom Enum description to a DataGrid,但在我的情況下,我有多個屬性。數據綁定enum屬性到網格和顯示描述

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 DataGridView的(實際上是一個DevExpress.XtraGrid.GridControl,而是一個通用的解決方案將得到更廣泛的應用)。我想要顯示描述而不是枚舉名稱。我怎樣才能做到這一點? (對類/枚舉/屬性沒有限制;我可以隨意更改它們。)

回答

10

A TypeConverter通常會完成這項工作;這裏有一些適用於DataGridView的代碼 - 只需添加代碼即可閱讀描述(通過反射等 - 我剛剛使用了字符串前綴來顯示自定義代碼的工作原理)。

請注意,您可能也想重寫ConvertFrom。可以在類型中指定轉換器(如果您只希望它應用某些屬性),並且還可以在運行時應用enum不受您控制的情況。

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

謝謝馬克!與我們的EnumHelper(類似於rally25rs的答案的第一部分)相結合,這個優雅的解決方案可以很好地工作 - 在DataGridView中。不幸的是我發現DevExpress.XtraGrid.GridControl不**檢測TypeConverter屬性。嘆。但你的回答顯然是正確的。 – TrueWill 2009-10-08 21:15:36

+1

...你指出我在正確的方向。我發現Developer Express並不打算支持這一點,並提供了這種解決方法:http://www.devexpress.com/Support/Center/p/CS2436.aspx – TrueWill 2009-10-08 21:21:16

5

我不知道多少,這會有所幫助,但我用枚舉的擴展方法,看起來像這樣:

/// <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」 屬性。

這可能有點過於複雜,但它的我想出了:)

+0

+1有一個很好的建議 - 謝謝;我們有一個EnumHelper類已經像你的例子,另一個開發人員建議字符串屬性,但我很懶。 ;) – TrueWill 2009-10-08 20:45:44

2

基於其他兩個答案,第一件事,我已經把一類,它可以任意枚舉之間一般轉換每個枚舉值都使用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); 
    } 
}