WinForms DataGridView:使用嵌套对象属性绑定对象(扩展列)

时间:2011-02-04 16:06:39

标签: c# .net winforms data-binding datagridview

这是Marc Gravels's answer

的变体

我会扩展Marc Gravels的有用示例,以通用的方式查看嵌套对象。但是System抛出System.Reflection.TargetException。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
public class Author
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
}
public class BookDetails
{
    public string Title { get; set; }
    public int TotalRating { get; set; }
    public int Occurrence { get; set; }
    public Author Author { get; set; }
}
//public class MyBindingSource<T> : BindingSource
class MyList<T> : List<T>, ITypedList
{
    public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
    {
        var origProps = TypeDescriptor.GetProperties(typeof(T));

        List<PropertyDescriptor> newProps = new List<PropertyDescriptor>(origProps.Count);
        foreach (PropertyDescriptor prop in origProps)
        {
            var childProps = TypeDescriptor.GetProperties(prop.GetType());
            if ((childProps.Count == 0) || isSimpleType(prop))
            {
                newProps.Add(prop);
            }
            else
            {
                foreach (PropertyDescriptor childProp in childProps)
                {
                    newProps.Add(new MyPropertyDescriptor(prop, childProp));
                }
            }

        }
        return new PropertyDescriptorCollection(newProps.ToArray());
    }

    private static bool isSimpleType(PropertyDescriptor prop)
    {
        if (prop.PropertyType.BaseType == typeof(ValueType)) return true;
        if (prop.PropertyType == typeof(string)) return true;
        if (prop.PropertyType.BaseType != typeof(Object)) return true;

        return false;
    }

    public string GetListName(PropertyDescriptor[] listAccessors)
    {
        return "";
    }
}
class MyPropertyDescriptor : PropertyDescriptor
{
    private static readonly Attribute[] nix = new Attribute[0];
    private readonly PropertyDescriptor parent;
    private readonly PropertyDescriptor child;
    public MyPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor child)
        : base(parent.Name + "." + child.Name, nix)
    {
        this.parent = parent;
        this.child = child;
    }
    public override object GetValue(object component)
    {
        return child.GetValue(component);
    }
    public override Type PropertyType
    {
        get { return child.PropertyType; }
    }
    public override bool IsReadOnly
    {
        get { return true; }
    }
    public override void SetValue(object component, object value)
    {
        throw new NotSupportedException();
    }
    public override void ResetValue(object component)
    {
        throw new NotSupportedException();
    }
    public override bool CanResetValue(object component)
    {
        return false;
    }
    public override Type ComponentType
    {
        get { return parent.ComponentType; }
    }
    public override bool ShouldSerializeValue(object component)
    {
        return false;
    }
}
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        var author1 = new Author()  { FirstName = "Victor", LastName = "Hugo"  };
        var author2 = new Author() { FirstName = "Moore", LastName = "Thomas" };
        var data = new MyList<BookDetails> { 
            new BookDetails { Title = "abc", TotalRating = 3, Occurrence = 2, Author = author1 }, 
            new BookDetails { Title = "def", TotalRating = 3, Occurrence = 2, Author = author2 }, 
            new BookDetails { Title = "ghi", TotalRating = 3, Occurrence = 2, Author = author1 }, 
            new BookDetails { Title = "jkl", TotalRating = 3, Occurrence = 2, Author = author2 }, 
        };
        Application.Run(new Form
        {
            Controls = { 
                new DataGridView { 
                    Dock = DockStyle.Fill, 
                    DataSource = data 
                } 
            }
        });
    }
}

2 个答案:

答案 0 :(得分:1)

您应该将prop.GetType()更改为prop.PropertyType

答案 1 :(得分:0)

我自己找到了解决方案:

错误发生在MyPropertyDescriptor中!

校正:

class MyPropertyDescriptor : PropertyDescriptor
{
    private static readonly Attribute[] nix = new Attribute[0];
    private readonly PropertyDescriptor parent;
    private readonly PropertyDescriptor child;
    public MyPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor child)
        : base(parent.Name + "." + child.Name, nix)
    {
        this.parent = parent;
        this.child = child;
    }
    public override object GetValue(object component)
    {
        var temp = parent.GetValue(component);
        if (temp == null) return null;
        var temp2 = child.GetValue(temp);
        return temp2;
    }
    public override Type PropertyType
    {
        get { return child.PropertyType; }
    }
    public override bool IsReadOnly
    {
        get { return true; }
    }
    public override void SetValue(object component, object value)
    {
        throw new NotSupportedException();
    }
    public override void ResetValue(object component)
    {
        throw new NotSupportedException();
    }
    public override bool CanResetValue(object component)
    {
        return false;
    }
    public override Type ComponentType
    {
        get { return parent.ComponentType; }
    }
    public override bool ShouldSerializeValue(object component)
    {
        return false;
    }
}