2014-02-27 1 views
2

DataGridView가있는 winforms 응용 프로그램이 있습니다. 이 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() 메소드를 오버라이드 (override)하기 위해 CustomTypeDescriptor의 서브 클래스를 만들려고 할 수 있습니다 내 자신의 목적을 위해,이 같은 DataTable을에 개체를 변환, 다른 방법을 가기로 결정했다. 그런 다음 자신의 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 스크립터

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