The following is a starter for you. Study to get acquainted with the basics then learn about TypeConverter for special property types. Note all code is in a form but each class should be in it's own file.
Imports System.ComponentModel
Imports System.Globalization
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim item As New AppSettings With {.Assigned = "Jim", .Description = "TODO", .Priority = Priority.High}
PropertyGrid1.SelectedObject = item
End Sub
Private Sub DetailsButton_Click(sender As Object, e As EventArgs) Handles DetailsButton.Click
Dim currentValues = CType(PropertyGrid1.SelectedObject, AppSettings)
Console.WriteLine()
End Sub
End Class
Public Class AppSettings
<Category("Main"), DisplayName("About"), Description("Some text to say about this property")>
Public Property Description() As String
<Category("Section 1"), Description("Priority of something")>
Public Property Priority() As Priority
<Category("Section 2"), Description("Person name")>
Public Property Assigned() As String
<Description("Name of the thing")>
Public Property Name() As String
<Description("Whether activated or not")>
Public Property Activated() As Boolean
<Description("Rank of the thing")>
Public Property Rank() As Integer
<Description("extra free-form attributes on this thing.")>
<Editor(
"System.Windows.Forms.Design.StringCollectionEditor," &
"System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
GetType(Drawing.Design.UITypeEditor))>
<TypeConverter(GetType(MyConverter))>
Public ReadOnly Property ExtraStuff() As List(Of String)
Get
If _attributes Is Nothing Then
_attributes = New List(Of String)()
End If
Return _attributes
End Get
End Property
Private _attributes As List(Of String)
End Class
Public Enum Priority
High
Medium
Low
End Enum
Public Class MyConverter
Inherits TypeConverter
Public Overrides Function ConvertTo(
context As ITypeDescriptorContext,
culture As CultureInfo, value As Object,
destinationType As Type) As Object
Dim list As List(Of String) = TryCast(value, List(Of String))
If destinationType Is GetType(String) Then
Return String.Join(",", list.ToArray())
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
And for list drop-down
Public Class FormatStringConverter
Inherits StringConverter
Public Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overrides Function GetStandardValuesExclusive(ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overrides Function GetStandardValues(context As ITypeDescriptorContext) As StandardValuesCollection
Dim list As New List(Of String) From {
"",
"Jim",
"Mary",
"Frank",
"Karen"
}
Return New StandardValuesCollection(list)
End Function
End Class
Add this to the base class
Private _formatString As String
<TypeConverter(GetType(FormatStringConverter))>
Public Property Names() As String
Get
Return _formatString
End Get
Set(ByVal value As String)
_formatString = value
End Set
End Property
---