Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleMake a TypeConverter for a collection in Visual Basic .NET
DescriptionThis example shows how to make a TypeConverter for a collection in Visual Basic .NET.
KeywordsTypeConverter, type converter, PropertyGrid, Properties window, collection, property, VB .NET
CategoriesControls, Software Engineering
 
For an introduction to making TypeConverters, see Make a type converter in VB .NET.

The key to making a type converter for a collection property is to make a new collection class that inherits from CollectionBase. Then make a type converter for that class.

The following code shows the AddressCollection class. This is simply a collection of StreetAddress objects. (Note: This collection is strongly typed so it can only hold StreetAddress objects. That has some benefits by itself. Because you cannot add a Person object to the collection, there are fewer chances for certain kinds of bugs. In general, you should use this type of strongly typed collection where possible. Note also that in Visual Basic 2005 you can use a generic Collection(Of StreetAddress) to get the same strong typing without the work of building your own collection class.)

Notice that this class provides a ToString method that returns a series of addresses in the form:L

    Street1,City1,State1;Street2,City2,State2;...

The class also has a constructor that takes a string in this format and adds appropriate StreetAddress objects to the collection.

 
Public Class AddressCollection
    Inherits CollectionBase

    Default Public Property Item(ByVal index As Integer) As _
        StreetAddress
        Get
            Return CType(List(index), StreetAddress)
        End Get
        Set(ByVal Value As StreetAddress)
            List(index) = Value
        End Set
    End Property

    Public Sub Add(ByVal street_address As StreetAddress)
        List.Add(street_address)
    End Sub

    Public Function IndexOf(ByVal value As StreetAddress) _
        As Integer
        Return List.IndexOf(value)
    End Function

    Public Sub Insert(ByVal index As Integer, ByVal value _
        As StreetAddress)
        List.Insert(index, value)
    End Sub

    Public Sub Remove(ByVal value As StreetAddress)
        List.Remove(value)
    End Sub

    Public Function Contains(ByVal value As StreetAddress) _
        As Boolean
        Return List.Contains(value)
    End Function

    Protected Overrides Sub OnInsert(ByVal index As _
        Integer, ByVal value As Object)
        If Not value.GetType() Is GetType(StreetAddress) _
            Then
            Throw New ArgumentException("Value must be of " & _
                "type StreetAddress.", "value")
        End If
    End Sub

    Protected Overrides Sub OnRemove(ByVal index As _
        Integer, ByVal value As Object)
        If Not value.GetType() Is GetType(StreetAddress) _
            Then
            Throw New ArgumentException("Value must be of " & _
                "type StreetAddress.", "value")
        End If
    End Sub

    Protected Overrides Sub OnSet(ByVal index As Integer, _
        ByVal oldValue As Object, ByVal newValue As Object)
        If Not newValue.GetType() Is GetType(StreetAddress) _
            Then
            Throw New ArgumentException("New value must be " & _
                "of type StreetAddress.", "newValue")
        End If
    End Sub

    Protected Overrides Sub OnValidate(ByVal value As _
        Object)
        If Not value.GetType() Is GetType(StreetAddress) _
            Then
            Throw New ArgumentException("Value must be of " & _
                "type StreetAddress.", "value")
        End If
    End Sub

    Public Sub New()
    End Sub
    Public Sub New(ByVal txt As String)
        Dim addresses() As String = txt.Split(New Char() _
            {";"})

        For Each address_text As String In addresses
            Try
                Me.List.Add(New StreetAddress(address_text))
            Catch
                Throw New InvalidCastException( _
                    "Invalid StreetAddress serialization '" _
                        & _
                    address_text & "'")
            End Try
        Next address_text
    End Sub

    Public Overrides Function ToString() As String
        Dim txt As String
        For Each street_address As StreetAddress In _
            MyBase.List
            txt &= ";" & street_address.ToString()
        Next street_address

        If txt.Length > 0 Then txt = txt.Substring(1)

        Return txt
    End Function
End Class
 
The following code shows the AddressCollection type converter. It uses the AddressCollection class's ToString and method and the constructor that takes a properly formatted string as input to convert to and from strings. See Make a type converter in VB .NET for more information about the details.
 
Public Class AddressCollectionConverter
    Inherits TypeConverter

    Public Overloads Overrides Function _
        CanConvertFrom(ByVal context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        sourceType As System.Type) As Boolean
        If (sourceType.Equals(GetType(String))) Then
            Return True
        Else
            Return MyBase.CanConvertFrom(context, _
                sourceType)
        End If
    End Function

    Public Overloads Overrides Function CanConvertTo(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        destinationType As System.Type) As Boolean
        If (destinationType.Equals(GetType(String))) Then
            Return True
        Else
            Return MyBase.CanConvertTo(context, _
                destinationType)
        End If
    End Function

    Public Overloads Overrides Function ConvertFrom(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        culture As System.Globalization.CultureInfo, ByVal _
        value As Object) As Object
        If (TypeOf value Is String) Then
            Dim txt As String = CType(value, String)
            Return New AddressCollection(txt)
        Else
            Return MyBase.ConvertFrom(context, culture, _
                value)
        End If
    End Function

    Public Overloads Overrides Function ConvertTo(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        culture As System.Globalization.CultureInfo, ByVal _
        value As Object, ByVal destinationType As _
        System.Type) As Object
        If (destinationType.Equals(GetType(String))) Then
            Return value.ToString()
        Else
            Return MyBase.ConvertTo(context, culture, _
                value, destinationType)
        End If
    End Function

    Public Overloads Overrides Function _
        GetPropertiesSupported(ByVal context As _
        ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overloads Overrides Function GetProperties(ByVal _
        context As ITypeDescriptorContext, ByVal value As _
        Object, ByVal Attribute() As Attribute) As _
        PropertyDescriptorCollection
        Return TypeDescriptor.GetProperties(value)
    End Function
End Class
 
Finally, the Person class includes a property of type AddressCollection. If you set a PropertyGrid's SelectedObject property to a Person object, the PropertyGrid uses the type converter to display the AddressCollection properly. It displays the word "Collection" and an ellipsis to the right for the property. If you click the ellipsis, it displays a collection editor where you can edit each of the StreetAdress objects.
 
Public Class Person
    ...
    Private m_Addresses As New AddressCollection
    Public Property Addresses() As AddressCollection
        Get
            Return m_Addresses
        End Get
        Set(ByVal Value As AddressCollection)
            m_Addresses = Value
        End Set
    End Property
    ...
End Class
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated