2014-02-27 51 views
2

我有一個winforms應用程序,它有一個DataGridView。我希望能夠將此DataGridView的DataSource設置爲任意的IEnumerable,以便它顯示該對象上的所有公共屬性和字段。默認情況下,DataGridView只顯示屬性.NET的DataGridView顯示對象字段

我知道如何重構類來將字段轉換爲屬性,但我更願意能夠在不進行重構的情況下執行此操作。 DataGridView有什麼技巧可以處理,它會指示它顯示字段,就好像它們是屬性一樣?也許我可以使用一些庫來將數據源中的對象轉換爲字段被封裝的代理?

更新:感謝所有的輸入。自定義類型描述符可能是一種最通用的方法,所以我把它算作一個正確的答案。對於我自己而言,我決定走另一條路,將對象轉換爲數據表,就像這樣:

var dt = new DataTable(); 
foreach (var o in (IEnumerable)data) 
{ 
    var r = dt.NewRow(); 
    foreach (var f in o.GetType().GetFields()) 
    { 
     if (!dt.Columns.Contains(f.Name)) 
     { 
      dt.Columns.Add(f.Name); 
     } 
     r[f.Name] = f.GetValue(o); 
    } 
    dt.Rows.Add(r); 
} 
dataGridView1.DataSource = dt; 
+0

它在技術上並不在DataGridView不允許此。它是內部使用的CurrencyManager類,只允許屬性而不允許使用字段。我想不出有什麼好辦法去做你想問的問題。 – test

+0

如果網格僅用於查看,您可以嘗試使用LINQ將IEnumerable對象轉換爲匿名對象,並在其中創建字段等的屬性。 – LarsTech

回答

1

你可以嘗試以覆蓋GetProperties()方法創建的CustomTypeDescriptor子類。然後你必須實現你自己的TypeDescriptionProvider類來設置它們在期望的類的TypeDescriptionProviderAttribute(它將被表示爲行)。
實施例:bind second-level properties

這是我的例子:

MyFieldsClass

[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))] 
internal class MyFieldsClass 
{ 
    public int IntField; 
    public double DoubleField; 
} 

FieldPropertyDescriptor

internal sealed class FieldPropertyDescriptor<TComponent, TField> : PropertyDescriptor 
{ 
    private readonly FieldInfo fieldInfo; 

    public FieldPropertyDescriptor(string name) 
     : base(name, null) 
    { 
     fieldInfo = typeof(TComponent).GetField(Name); 
    } 

    public override bool IsReadOnly { get { return false; } } 
    public override void ResetValue(object component) { } 
    public override bool CanResetValue(object component) { return false; } 
    public override bool ShouldSerializeValue(object component) 
    { 
     return true; 
    } 

    public override Type ComponentType 
    { 
     get { return typeof(TComponent); } 
    } 
    public override Type PropertyType 
    { 
     get { return typeof(TField); } 
    } 

    public override object GetValue(object component) 
    { 
     return fieldInfo.GetValue(component); 
    } 

    public override void SetValue(object component, object value) 
    { 
     fieldInfo.SetValue(component, value); 
     OnValueChanged(component, EventArgs.Empty); 
    } 
} 

MyCustomTypeDe scriptor

internal sealed class MyCustomTypeDescriptor : CustomTypeDescriptor 
{ 
    public MyCustomTypeDescriptor(ICustomTypeDescriptor parent) 
     : base(parent) 
    { 
    } 

    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
    { 
     return GetProperties(); 
    } 

    public override PropertyDescriptorCollection GetProperties() 
    { 
     return AddItems(base.GetProperties(), 
      new FieldPropertyDescriptor<MyFieldsClass, int>("IntField"), 
      new FieldPropertyDescriptor<MyFieldsClass, double>("DoubleField")); 
    } 

    private static PropertyDescriptorCollection AddItems(PropertyDescriptorCollection cols, params PropertyDescriptor[] items) 
    { 
     PropertyDescriptor[] array = new PropertyDescriptor[cols.Count + items.Length]; 
     cols.CopyTo(array, 0); 
     for (int i = 0; i < items.Length; i++) 
      array[cols.Count + i] = items[i]; 
     PropertyDescriptorCollection newcols = new PropertyDescriptorCollection(array); 
     return newcols; 
    } 
} 

MyTypeDescriptionProvider

internal sealed class MyTypeDescriptionProvider : TypeDescriptionProvider 
{ 
    private ICustomTypeDescriptor td; 

    public MyTypeDescriptionProvider() 
     : this(TypeDescriptor.GetProvider(typeof(MyFieldsClass))) 
    { 
    } 
    public MyTypeDescriptionProvider(TypeDescriptionProvider parent) 
     : base(parent) 
    { 
    } 
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) 
    { 
     return td ?? (td = new MyCustomTypeDescriptor(base.GetTypeDescriptor(objectType, instance))); 
    } 
} 

用例:

dataGridView1.DataSource = new List<MyFieldsClass>(new[] { new MyFieldsClass { IntField = 1, DoubleField = 10.0 } }); 
+0

添加示例:如何將類的字段填充到「DataGridView」中。 – Dmitry

相關問題