2009-10-08 10 views
11

To jest podobne pytanie do How to bind a custom Enum description to a DataGrid, ale w moim przypadku mam wiele właściwości.Właściwości powiązania enum danych z siatką i opisem wyświetlacza

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

Jestem wiązania BindingList <TestResult> do WinForms DataGridView (właściwie DevExpress.XtraGrid.GridControl, ale ogólny rozwiązanie byłoby bardziej powszechnie stosowane). Chcę, aby pojawiały się opisy, a nie nazwy wyliczeniowe. Jak mogę to zrobić? (Nie ma żadnych ograniczeń dotyczących klasy/enum/atrybutów, mogę je dowolnie zmieniać.)

Odpowiedz

10

Zwykle wykonuje to zadanie; oto kod, który działa na DataGridView - po prostu dodaj swój kod, aby przeczytać opisy (poprzez odbicie itp. - właśnie użyłem prefiksu ciągu na teraz, aby pokazać działający kod niestandardowy).

Pamiętaj, że prawdopodobnie chcesz zastąpić także ConvertFrom. Konwerter można określić na poziomie właściwości (na wypadek, gdyby dotyczyć tylko niektórych właściwości), i można go również zastosować w środowisku wykonawczym, jeśli wyliczenie nie znajduje się pod kontrolą użytkownika.

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

Dzięki Marc! W połączeniu z naszym EnumHelper (podobnym do pierwszej części odpowiedzi rally25rs), to eleganckie rozwiązanie działa pięknie - w DataGridView. Niestety znalazłem, że DevExpress.XtraGrid.GridControl nie ** wykrywa atrybutu TypeConverter. Westchnienie. Ale twoja odpowiedź jest wyraźnie poprawna. – TrueWill

+1

... i wskazałeś mi właściwy kierunek. Zauważyłem, że program Developer Express nie planuje obsługiwać tego rozwiązania i oferuje to obejście: http://www.devexpress.com/Support/Center/p/CS2436.aspx – TrueWill

5

Nie jestem pewien, ile to pomaga, ale używam metodę rozszerzenia na Enum, który wygląda tak:

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

Można użyć niestandardowej właściwości getter na obiekcie, aby przywrócić Nazwa:

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

Następnie związać swoją siatkę do "RequiredExpectationResultDescr" i "NonRequiredExpectationResultDescr" właściwości.

To może być trochę zbyt skomplikowane, ale jego 1st rzecz wymyśliłem :)

+0

+1 za dobrą sugestię - dziękuję; mamy klasę EnumHelper już podobną do twojego przykładu, a inny programista sugerował właściwości ciągu, ale jestem leniwy. ;) – TrueWill

2

podstawie dwóch innych odpowiedzi, mam połączyć klasę, która może ogólnie konwersji pomiędzy dowolnym wyliczenia i ciąg znaków za pomocą atrybutu Opis dla każdej wartości wyliczenia.

To wykorzystuje System.ComponentModel dla definicji DescriptionAttribute i obsługuje tylko konwersję między T i 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); 
    } 
} 
Powiązane problemy