c#winforms应用程序中datagridview/controls中的子级对象属性绑定

Awa*_*dra 6 c# c#-4.0

在使用绑定对象列表到datagridview或控件时,我遇到了问题.实际上我想要的是,我有课时说Person,Address而且Contact.Personclass有3个属性,一个是string Add类型的Name,类型是Address,最后一个是Conttype Contact.通过谷歌搜索我发现我必须创建我创建的CustomTypeDescriptor类,它只适用于Contact或为一个类Address.当我们放两次然后它显示编译时错误,不能有重复[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider<Contact>))].

我怎么解决这个问题.

在这里,我提供了我想要实现的示例代码,

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.AutoGenerateColumns = false;

        dataGridView1.Columns.Add("Name", "Name");
        dataGridView1.Columns.Add("City", "City");
        dataGridView1.Columns.Add("ContactName", "ContactName");

        dataGridView1.Columns["Name"].DataPropertyName = "Name";
        dataGridView1.Columns["City"].DataPropertyName = "Add_City";
        dataGridView1.Columns["ContactName"].DataPropertyName = "Cont_ContactName";

        List<Person> PersonList = PersonProxy.GetPersonCollection();
        dataGridView1.DataSource = PersonList;
    }
}



public class PersonProxy
{
    public static List<Person> GetPersonCollection()
    {
        List<Person> persList = new List<Person>();

        persList.Add(new Person
        {
            Name = "Awadhendra",
            Add = new Address
            {
                City = "Allahabad"
            },
            Cont = new Contact
            {
                ContactName = "Awadh"
            }
        });

        persList.Add(new Person
        {
            Name = "Alok",
            Add = new Address
            {
                City = "Allahabad"
            },
            Cont = new Contact
            {
                ContactName = "Alok"
            }
        });

        persList.Add(new Person
        {
            Name = "Ankit",
            Add = new Address
            {
                City = "Lucknow"
            },
            Cont = new Contact
            {
                ContactName = "Ankit"
            }
        });

        persList.Add(new Person
        {
            Name = "Swati",
            Add = new Address
            {
                City = "Lucknow"
            },
            Cont = new Contact
            {
                ContactName = "Awadh"
            }
        });

        return persList;
    }
}


[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider<Contact>))]    
public class Person
{
    public string Name { get; set; }
    public Address Add { get; set; }    ////How to get address and contact both for binding.        
    public Contact Cont { get; set; }  ////Write now am getting Contact
}

public class Address
{
    public string City { get; set; }
}

public class Contact
{
    public string ContactName { get; set; }
}

public class MyTypeDescriptionProvider<T> : TypeDescriptionProvider
{
    private ICustomTypeDescriptor td;
    public MyTypeDescriptionProvider()
        : this(TypeDescriptor.GetProvider(typeof(Person)))
    {
    }
    public MyTypeDescriptionProvider(TypeDescriptionProvider parent)
        : base(parent)
    {
    }
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        if (td == null)
        {
            td = base.GetTypeDescriptor(objectType, instance);
            td = new MyCustomTypeDescriptor(td, typeof(T));
        }
        return td;
    }
}

public class SubPropertyDescriptor : PropertyDescriptor
{
    private PropertyDescriptor _subPD;
    private PropertyDescriptor _parentPD;

    public SubPropertyDescriptor(PropertyDescriptor parentPD, PropertyDescriptor subPD, string pdname)
        : base(pdname, null)
    {
        _subPD = subPD;
        _parentPD = parentPD;
    }

    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 _parentPD.ComponentType; }
    }
    public override Type PropertyType { get { return _subPD.PropertyType; } }

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

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

public class MyCustomTypeDescriptor : CustomTypeDescriptor
{
    Type typeProperty;
    public MyCustomTypeDescriptor(ICustomTypeDescriptor parent, Type type)
        : base(parent)
    {
        typeProperty = type;
    }
    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        PropertyDescriptorCollection cols = base.GetProperties(attributes);

        string propertyName = "";
        foreach (PropertyDescriptor col in cols)
        {
            if (col.PropertyType.Name == typeProperty.Name)
                propertyName = col.Name;
        }
        PropertyDescriptor pd = cols[propertyName];
        PropertyDescriptorCollection children = pd.GetChildProperties();
        PropertyDescriptor[] array = new PropertyDescriptor[cols.Count + children.Count];
        int count = cols.Count;
        cols.CopyTo(array, 0);

        foreach (PropertyDescriptor cpd in children)
        {
            array[count] = new SubPropertyDescriptor(pd, cpd, pd.Name + "_" + cpd.Name);
            count++;
        }

        PropertyDescriptorCollection newcols = new PropertyDescriptorCollection(array);
        return newcols;
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢,

Bol*_*olu 3

基于MSDN

有两种方法将 aTypeDescriptionProvider与 a关联TypeDescriptor:

  • 在设计时,可以为目标类分配适当的 TypeDescriptionProviderAttribute标记。
  • 在运行时,可以调用该类AddProvider的方法之一。TypeDescriptor这些重载方法需要目标对象或其类类型。

所以只需在运行时添加它们:

private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.AutoGenerateColumns = false;

        dataGridView1.Columns.Add("Name", "Name");
        dataGridView1.Columns.Add("City", "City");
        dataGridView1.Columns.Add("ContactName", "ContactName");

        dataGridView1.Columns["Name"].DataPropertyName = "Name";
        dataGridView1.Columns["City"].DataPropertyName = "Add_City";
        dataGridView1.Columns["ContactName"].DataPropertyName = "Cont_ContactName";

        List<Person> PersonList = PersonProxy.GetPersonCollection();

        //add them here
        System.ComponentModel.TypeDescriptor.AddProvider((new MyTypeDescriptionProvider<Address>()), typeof(Person));
        System.ComponentModel.TypeDescriptor.AddProvider((new MyTypeDescriptionProvider<Contact>()), typeof(Person));
        dataGridView1.DataSource = PersonList;
    }
Run Code Online (Sandbox Code Playgroud)