|
|
Title | Make a TypeConverter for a collection in Visual Basic .NET |
Description | This example shows how to make a TypeConverter for a collection in Visual Basic .NET. |
Keywords | TypeConverter, type converter, PropertyGrid, Properties window, collection, property, VB .NET |
Categories | Controls, 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
|
|
|
|
|
|