title: Expand collection in property grid without any modifications to the class?
body: <p>This approach works for everything but collections:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/24151066/expand-custom-object-in-property-grid-without-any-modifications-to-the-class">Expand custom object in property grid without any modifications to the class?</a></li>
  </ul>
  
  <p>Collections are displayed like this:</p>
  
  <p><img src="https://i.stack.imgur.com/2CCjV.png" alt="enter image description here"></p>
  
  <p>So even though they are expandable, there isn't much use for them inside property grid.</p>
  
  <p>Here is an example of what I am looking for (screenshot taken from <a href="http://www.codeproject.com/Articles/4448/Customized-display-of-collection-data-in-a-Propert" rel="nofollow noreferrer">here</a>):</p>
  
  <p><img src="https://i.stack.imgur.com/Rt7Ob.png" alt="enter image description here"></p>
  
  <p>The linked article also contains some code, which would make this happen, but it <strong>requires modifying the original class</strong>. Between it and my previous question, I came up with some ideas, but I'm not very fluent in using <code>System.ComponentModel</code> namespace.</p>
  
  <p>Here is a reduced test case (custom class with one property of collection type, which contains one object of custom type, which has one string property):</p>
  
  <pre class="lang-vb prettyprint-override"><code>Imports System.ComponentModel
  
  Public Class Form1
  
    Sub New()
      ' This call is required by the designer.
      InitializeComponent()
  
      ' Add any initialization after the InitializeComponent() call.
      Me.AssignTypeConverter(Of MyCustomClassCollection, ExpandableObjectConverter)()
    End Sub
  
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
      Dim collection As New MyCustomClassCollection
      collection.Add(New MyCustomClass With {.MyCustomProperty = "Hello"})
  
      Dim container As New MyCustomClassCollectionContainer(collection)
  
      Me.PropertyGrid1.SelectedObject = container
    End Sub
  
    Private Sub AssignTypeConverter(Of IType, IConverterType)()
      System.ComponentModel.TypeDescriptor.AddAttributes(GetType(IType),
        New System.ComponentModel.TypeConverterAttribute(GetType(IConverterType)))
    End Sub
  
  End Class
  
  
  Public Class MyCustomClass
    Public Property MyCustomProperty As String
  End Class
  
  Public Class MyCustomClassCollection : Inherits System.Collections.ObjectModel.Collection(Of MyCustomClass)
  End Class
  
  Public Class MyCustomClassCollectionContainer
  
    Dim _items As MyCustomClassCollection
  
    Public ReadOnly Property Items As MyCustomClassCollection
      Get
        Return _items
      End Get
    End Property
  
    Sub New(items As MyCustomClassCollection)
      _items = items
    End Sub
  
  End Class
  </code></pre>
  
  <p>Proposed solution (pseudo-code, does not compile)</p>
  
  <pre class="lang-vb prettyprint-override"><code>Imports System.ComponentModel
  
  Public Class MyCustomClassTypeDescriptor : Inherits ExpandableObjectConverter
  
    Public Overrides Function GetProperties(context As ITypeDescriptorContext,
                                  value As Object, attributes() As Attribute) _
                                              As PropertyDescriptorCollection
      Dim pds As New PropertyDescriptorCollection(Nothing)
      Dim lst As IList(Of Object) = DirectCast(value, IList)
      For i As Integer = 0 To lst.Count - 1
        Dim item As MyCustomClass = DirectCast(lst.Item(i), MyCustomClass)
        'compile error - abstract class cannot be instantiated
        Dim pd As New PropertyDescriptor(item)
        pds.Add(pd)
      Next
      Return pds
    End Function
  
  End Class
  </code></pre>
  
  <p>And then apply this custom object converter at runtime.</p>
  
  <p>Is it going to work like this? What am I missing? Any suggestions are welcome!</p>
  
  <p><strong>Note:</strong> The above is VB.NET, but if you speak C#, feel free to use it.</p>