2013-01-10 11 views
5

में नियंत्रण मैं एक समस्या में फंस कर रहा हूँ DataGridView या नियंत्रण में वस्तु सूची बंधन के साथ काम करते। असल में मैं क्या चाहता हूं, मेरे पास कक्षा है Person, Address और ContactPerson कक्षा में 3 गुण हैं एक प्रकार का प्रकार स्ट्रिंग, Add प्रकार का पता और अंतिम 0 Cont प्रकार Contact है। गुगलिंग से मैंने पाया कि मुझे CustomTypeDescriptor कक्षा बनाना है जो मैंने बनाया है और यह केवल Contact या Address के लिए केवल एक वर्ग के लिए काम करता है। जब हम दो बार डालते हैं तो यह संकलन समय त्रुटि दिखाता है जिसमें डुप्लिकेट [TypeDescriptionProvider(typeof(MyTypeDescriptionProvider<Contact>))] नहीं हो सकता है।बाल स्तर वस्तु संपत्ति DataGridView में बाध्यकारी/सी # WinForms आवेदन

मैं इस समस्या को कैसे हल कर सकता हूं।

यहाँ मैं नमूना कोड जो मैं लागू करने के लिए कोशिश कर रहा हूँ,

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

धन्यवाद,

उत्तर

3

MSDN

के आधार पर वहाँ एक TypeDescriptor के साथ एक TypeDescriptionProvider संबद्ध करने के लिए दो तरीके हैं प्रदान कर रहा हूँ :

  • डिज़ाइन समय पर, जब लक्षित वर्ग को उचित TypeDescriptionProviderAttribute टैग असाइन किया जा सकता है।
  • रन समय
  • , जब TypeDescriptor वर्ग के AddProvider तरीकों में से एक कहा जा सकता है। इन अधिभारित विधियों को या तो लक्ष्य वस्तु या उसके वर्ग प्रकार की आवश्यकता होती है।

तो बस उन्हें क्रम में जोड़ें:

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

मैं .NET 4.5, पिछले जवाब लगभग काम करता है के साथ पाया है, लेकिन इस मुद्दे को AddProvider विधि में कार्य करता है कि के रूप में एक पिछले एक जीतता है, इसलिए हम केवल अनुबंध से गुण देखते हैं लेकिन पता नहीं।

समाधान श्रृंखला प्रदाताओं को एक साथ तो हम प्राप्त करने के लिए है ...

//add them here 
var addressProvider = new MyTypeDescriptionProvider<Address>(); 
System.ComponentModel.TypeDescriptor.AddProvider(t1, typeof(Person)); 
System.ComponentModel.TypeDescriptor.AddProvider(new MyTypeDescriptionProvider<Contact>(t1), typeof(Person)); 
संबंधित मुद्दे