.NET DataGridView的显示对象字段 [英] .NET DataGridView to show object fields

查看:123
本文介绍了.NET DataGridView的显示对象字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WinForms应用程序,它有一个DataGridView。我希望能够设置数据源这个DataGridView中的一个任意IEnumerable的,因此,它显示了对象的所有公共属性和字段。默认情况下的DataGridView只显示属性

我不知道如何重构类转换领域的财产,但我会preFER才能够做到这一点不重构。有什么样的技巧,我可以做的DataGridView,这将指示它显示领域,如果他们的属性?也许我可以用一些库的数据源中的对象转换为自己的代理,其中场包裹?

更新:感谢所有的输入。自定义类型的描述可能是一个最通用的方法,所以我算它作为一个正确的答案。对于我自己而言,我决定走另一条路,将对象转换为数据表中,像这样的:

  VAR DT =新的DataTable();
的foreach(VAR o在(IEnumerable的)数据)
{
    变种R = dt.NewRow();
    的foreach(VAR f由于o.GetType()。GetFields())
    {
        如果(!dt.Columns.Contains(f.Name))
        {
            dt.Columns.Add(f.Name);
        }
         -  [R [f.Name] = f.GetValue(O);
    }
    dt.Rows.Add(r)的;
}
dataGridView1.DataSource = DT;
 

解决方案

您可以尝试以覆盖的GetProperties,创建 CustomTypeDescriptor 的子类()方法。然后,你必须实现自己的 TypeDescriptionProvider 类来设置他们在 TypeDescriptionProviderAttribute 所需的类(这将重新$的psented为行p $)。
例如:<一href="http://blogs.msdn.com/b/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx?Redirected=true"相对=nofollow>绑定第二级属性

下面是我的例子:

MyFieldsClass

  [TypeDescriptionProvider(typeof运算(MyTypeDescriptionProvider))]
内部类MyFieldsClass
{
    公众诠释IntField;
    公共双DoubleField;
}
 

FieldPropertyDescriptor

 内部密封类FieldPropertyDescriptor&LT; TComponent的,TField&GT; :的PropertyDescriptor
{
    私人只读字段信息字段信息;

    公共FieldPropertyDescriptor(字符串名称)
        :基地(名,空)
    {
        字段信息= typeof运算(TComponent的).GetField(名称);
    }

    公众覆盖BOOL的IsReadOnly {{返回FALSE; }}
    公众覆盖无效ResetValue(对象组件){}
    公众覆盖布尔CanResetValue(对象组件){返回false; }
    公众覆盖布尔ShouldSerializeValue(对象组件)
    {
        返回true;
    }

    公众覆盖类型COMPONENTTYPE
    {
        {返回的typeof(TComponent的); }
    }
    公众覆盖类型属性类型
    {
        {返回的typeof(TField); }
    }

    公众覆盖对象的GetValue(对象组件)
    {
        返回fieldInfo.GetValue(组件);
    }

    公众覆盖无效的SetValue(组件对象,对象的值)
    {
        fieldInfo.SetValue(组件,值);
        OnValueChanged(组件,EventArgs.Empty);
    }
}
 

MyCustomTypeDescriptor

 内部密封类MyCustomTypeDescriptor:CustomTypeDescriptor
{
    公共MyCustomTypeDescriptor(ICustomTypeDescriptor父)
        :基地(父)
    {
    }

    公众覆盖PropertyDescriptorCollection的GetProperties,(属性[]属性)
    {
        返回的GetProperties();
    }

    公众覆盖PropertyDescriptorCollection的GetProperties,()
    {
        返回为addItems(base.GetProperties(),
            新FieldPropertyDescriptor&LT; MyFieldsClass,INT&GT;(IntField),
            新FieldPropertyDescriptor&LT; MyFieldsClass,双&GT;(DoubleField));
    }

    私有静态PropertyDescriptorCollection为addItems(PropertyDescriptorCollection COLS,PARAMS的PropertyDescriptor []项)
    {
        的PropertyDescriptor []数组=新的PropertyDescriptor [cols.Count + items.Length]。
        cols.CopyTo(阵列,0);
        的for(int i = 0; I&LT; items.Length;我++)
            阵列[cols.Count +我=项[I]
        PropertyDescriptorCollection newcols =新PropertyDescriptorCollection(阵列);
        返回newcols;
    }
}
 

MyTypeDescriptionProvider

 内部密封类MyTypeDescriptionProvider:TypeDescriptionProvider
{
    私人ICustomTypeDescriptor运输署;

    公共MyTypeDescriptionProvider()
        :这个(TypeDescriptor.GetProvider(typeof运算(MyFieldsClass)))
    {
    }
    公共MyTypeDescriptionProvider(TypeDescriptionProvider父)
        :基地(父)
    {
    }
    公众覆盖ICustomTypeDescriptor GetTypeDescriptor(类型的​​objectType,对象实例)
    {
        返回TD? (TD =新MyCustomTypeDescriptor(base.GetTypeDescriptor(的objectType,实例)));
    }
}
 

使用方法例如:

  dataGridView1.DataSource =新的名单,其中,MyFieldsClass&GT;(新[] {新MyFieldsClass {IntField = 1,DoubleField = 10.0}});
 

I have a winforms application, which has a DataGridView. I want to be able to set DataSource of this DataGridView to an arbitrary IEnumerable, so that it shows all public properties AND fields on that object. By default DataGridView only shows properties

I do know how to refactor classes to convert field to property, but I would prefer to be able to do it without refactoring. Is there any sort of trick I could do on DataGridView, which would instruct it to show fields as if they were properties? Maybe I could use some library to convert objects within data source to their proxy where fields are wrapped?

UPDATE: thanks all for the input. Custom type descriptor is likely a most generic method, so I counted it as a correct answer. For my own purpose, I decided to go another way, converting the object to DataTable, like this:

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;

解决方案

You can try to create subclass of CustomTypeDescriptor in order to override the GetProperties() method. Then you have to implement your own TypeDescriptionProvider class to set them in the TypeDescriptionProviderAttribute of desired class (which will be represented as row).
Example: bind second-level properties

Here is my example:

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

MyCustomTypeDescriptor

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

Usage example:

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

这篇关于.NET DataGridView的显示对象字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆