DataGridView: properties of T not shown when using ICollection<T>, but shown when using List<T>

I have a class that implements ICollection<T>, because I don’t want all functions of a List<T>. I also need to register an event handler inside the Add method. My whole code with sample data:

        public Form1()         {             InitializeComponent();              Random rnd = new Random();             List<ElementContainer> list = new List<ElementContainer>();              for (int i = 0; i < 9; i++)             {                 ElementContainer c = new ElementContainer()                 {                     Name = "Name " + (i + 1).ToString(),                     Number = Guid.NewGuid().ToString()                 };                  for (int j = 0; j < 12; j++)                 {                     Element el = new Element()                     {                         Name = "Element " + (12 * i + j).ToString(),                         Value1 = rnd.NextDouble(),                         Value2 = rnd.Next(10, 100),                         Value3 = rnd.Next(100, 1000)                     };                     c.Elements.Add(el);                 }                 list.Add(c);             }             ContainerBindingSource.DataSource = list;             CollectionBindingSource.DataSource = ContainerBindingSource;             CollectionBindingSource.DataMember = "Elements";             elementsDataGridView.AutoGenerateColumns = true;             elementsDataGridView.DataSource = CollectionBindingSource;         }     }      public class ElementContainer     {         public ElementContainer()         {             Elements = new ElementCollection();         }          public ElementCollection Elements { get; set; }         public string Name { get; set; }         public string Number { get; set; }     }      public class ElementCollection : ICollection<Element>     {         private readonly List<Element> internList = new List<Element>();          public int Count => internList.Count;         public bool IsReadOnly => false;         public void Add(Element item) => internList.Add(item);         public void Clear() => internList.Clear();         public bool Contains(Element item) => internList.Contains(item);         public void CopyTo(Element[] array, int arrayIndex) => internList.CopyTo(array, arrayIndex);         public bool Remove(Element item) => internList.Remove(item);         public IEnumerator<Element> GetEnumerator() => internList.GetEnumerator();         IEnumerator IEnumerable.GetEnumerator() => internList.GetEnumerator();     }      //public class ElementCollection : List<Element>     //{ }      public class Element     {         public string Name { get; set; }         public double Value1 { get; set; }         public double Value2 { get; set; }         public double Value3 { get; set; }     } 

At first sight everything looks good and as expected. BUT when using a BindingNavigator to move between the records I get an exception:

enter image description here

The BindingSource thinks the underlying type is ElementCollection instead of Element, even though the CollectionBindingSource has DataMemberset to "Elements". If I would set up all the binding via Visual Studios Form designer the DataGridView would show me the columns "Count" and "IsReadOnly", which actually match ElementCollection. It looks like this:

enter image description here Remember: This is the result only when using the designer for managing the DataBinding!


Now the different part with List<T>. Below is the complete code I used.

        public Form1()         {             InitializeComponent();              Random rnd = new Random();             List<ElementContainer> list = new List<ElementContainer>();              for (int i = 0; i < 9; i++)             {                 ElementContainer c = new ElementContainer()                 {                     Name = "Name " + (i + 1).ToString(),                     Number = Guid.NewGuid().ToString()                 };                  for (int j = 0; j < 12; j++)                 {                     Element el = new Element()                     {                         Name = "Element " + (12 * i + j).ToString(),                         Value1 = rnd.NextDouble(),                         Value2 = rnd.Next(10, 100),                         Value3 = rnd.Next(100, 1000)                     };                     c.Elements.Add(el);                 }                 list.Add(c);             }             ContainerBindingSource.DataSource = list;             CollectionBindingSource.DataSource = ContainerBindingSource;             CollectionBindingSource.DataMember = "Elements";             elementsDataGridView.AutoGenerateColumns = true;             elementsDataGridView.DataSource = CollectionBindingSource;         }     }      public class ElementContainer     {         public ElementContainer()         {             Elements = new ElementCollection();         }          public ElementCollection Elements { get; set; }         public string Name { get; set; }         public string Number { get; set; }     }      public class ElementCollection : List<Element>     {     }      public class Element     {         public string Name { get; set; }         public double Value1 { get; set; }         public double Value2 { get; set; }         public double Value3 { get; set; }     } 

As you can see I replaced the definition of ElementCollection. It’s not implementing ICollection<Element> anymore. Instead it inherits the whole List<Element>. Now I can freely move between all records without any exceptions.

enter image description here

Why doesn’t recognize the DataGridView the underlying type correctly when I use a type that implements ICollection<T>? But recognize it correctly when I use a type which inherits from List<T>? How do I have to implement ElementCollection to work as expected? Remember the fact that I cannot use List<T> as I have to handle events from underlying elements. A List<T> would make it more complicated and inconsistent.

Any help is appreciated.

Why doesn’t detect the DataGridView the properties of Element when using ICollection<T>? This also happens when I implement IList<T>. What makes the class List<T> different?

Add Comment
0 Answer(s)

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.