2009-10-08 3 views
11

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

나는 윈폼 DataGridView에로는 바인딩 <TestResult>을 결합하고 있습니다 (실제로는 DevExpress.XtraGrid.GridControl하지만 일반적인 솔루션은보다 광범위하게 적용 할 것). 열거 형 이름보다는 설명이 필요합니다. 이것을 어떻게 할 수 있습니까? (클래스/열거 형/애트리뷰트에는 제약이 없으며 원하는대로 변경할 수 있습니다.)

답변

10

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

감사합니다. Marc! EnumHelper (rally25rs의 답변의 첫 번째 부분과 유사)와 결합 된이 우아한 솔루션은 DataGridView에서 아름답게 작동합니다. 불행히도 DevExpress.XtraGrid.GridControl은 ** TypeConverter 특성을 감지하지 않음 **을 발견했습니다. 한숨. 하지만 당신의 대답은 분명 정확합니다. – TrueWill

+1

... 그리고 당신은 올바른 방향으로 나를 지적했습니다. Developer Express가이 문제를 지원할 계획이 아니며 다음 해결 방법을 제공한다는 사실을 알았습니다. http://www.devexpress.com/Support/Center/p/CS2436.aspx – TrueWill

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

당신은을 반환하는 개체에 사용자 지정 속성 게터를 사용할 수를 이름 :

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

2

내놓았다 1 일, 나는 함께 일반적으로 임의의 열거 사이에 변환 할 수있는 클래스를 뒀다 각 enum 값에 Description 속성을 사용하는 문자열.

설명 DescriptionAttribute 정의에 System.ComponentModel을 사용하며 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); 
    } 
}