I used the ideas from this post to create a custom collection of my custom class, so that I would be able to easily sort my collection. My project uses binary serialization to save everything (well the important stuff anyway) to a file. The problem is that my custom collection now breaks the serialization.

I can't seem to figure out how to get the custom collection to serialize!

Here is my code for the custom collection class:

VB.NET Code:
  1. Imports System.ComponentModel
  2. Imports System.Runtime.Serialization
  3. Imports System.Runtime.Serialization.Formatters.Binary
  4.  
  5. <Serializable()> _
  6. Public Class FGSDataCollection
  7.     Inherits System.ComponentModel.BindingList(Of FGSData)
  8.  
  9.     Implements ISerializable
  10.  
  11. #Region "Initializer"
  12.     Public Sub New()
  13.         ' need this for new empty list
  14.     End Sub
  15. #End Region 'Initializer
  16.  
  17. #Region "Types"
  18.     Private Class FGSDataComparer
  19.         Implements System.Collections.Generic.IComparer(Of FGSData)
  20.  
  21.         Private prop As PropertyDescriptor
  22.         Private direction As ListSortDirection
  23.  
  24.         Public Function Compare(ByVal x As FGSData, ByVal y As FGSData) As Integer Implements IComparer(Of FGSData).Compare
  25.             Dim result As Integer = DirectCast(Me.prop.GetValue(x), IComparable).CompareTo(Me.prop.GetValue(y))
  26.  
  27.             If Me.direction = ListSortDirection.Descending Then
  28.                 result = -result
  29.             End If
  30.  
  31.             Return result
  32.         End Function
  33.  
  34.         Public Sub New(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
  35.             Me.prop = prop
  36.             Me.direction = direction
  37.         End Sub
  38.     End Class
  39. #End Region 'Types
  40.  
  41. #Region "Variables"
  42.     Private _sort As String
  43.     Private _sortProperty As PropertyDescriptor
  44.     Private _sortDirection As ListSortDirection
  45. #End Region 'Variables
  46.  
  47. #Region "Properties"
  48.     Public Property Sort() As String
  49.         Get
  50.             Return Me._sort
  51.         End Get
  52.         Set(ByVal value As String)
  53.             Dim prop As PropertyDescriptor = Nothing
  54.             Dim direction As ListSortDirection
  55.  
  56.             Me.ParseSortClause(value, prop, direction)
  57.             Me._sort = value
  58.  
  59.             If prop Is Nothing Then
  60.                 Me.RemoveSortCore()
  61.             Else
  62.                 Me.ApplySortCore(prop, direction)
  63.             End If
  64.         End Set
  65.     End Property
  66.  
  67.     Protected Overrides ReadOnly Property SortDirectionCore() As System.ComponentModel.ListSortDirection
  68.         Get
  69.             Return Me._sortDirection
  70.         End Get
  71.     End Property
  72.  
  73.     Protected Overrides ReadOnly Property SortPropertyCore() As System.ComponentModel.PropertyDescriptor
  74.         Get
  75.             Return Me._sortProperty
  76.         End Get
  77.     End Property
  78.  
  79.     Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
  80.         Get
  81.             Return True
  82.         End Get
  83.     End Property
  84. #End Region 'Properties
  85.  
  86. #Region "Methods"
  87.     Protected Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
  88.         Me._sortProperty = prop
  89.         Me._sortDirection = direction
  90.  
  91.         Dim upperBound As Integer = Me.Items.Count - 1
  92.         Dim items(upperBound) As FGSData
  93.  
  94.         Me.Items.CopyTo(items, 0)
  95.  
  96.         Array.Sort(items, New FGSDataComparer(prop, direction))
  97.  
  98.         For index As Integer = 0 To upperBound
  99.             Me.Items(index) = items(index)
  100.         Next
  101.  
  102.         Me.OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, 0))
  103.     End Sub
  104.  
  105.     Protected Overrides Sub RemoveSortCore()
  106.         Me._sortProperty = Nothing
  107.         Me._sortDirection = Nothing
  108.     End Sub
  109.  
  110.     Private Sub ParseSortClause(ByVal clause As String, _
  111.                                 ByRef prop As PropertyDescriptor, _
  112.                                 ByRef direction As ListSortDirection)
  113.         If clause IsNot Nothing AndAlso clause.Trim() <> String.Empty Then
  114.             Dim parts As String() = clause.Split(" "c)
  115.  
  116.             If parts.Length > 2 Then
  117.                 Throw New ArgumentException("Invalid sort clause")
  118.             End If
  119.  
  120.             For index As Integer = 0 To parts.GetUpperBound(0)
  121.                 parts(index) = parts(index).Trim()
  122.             Next
  123.  
  124.             prop = TypeDescriptor.GetProperties(GetType(FGSData))(parts(0))
  125.  
  126.             If prop Is Nothing Then
  127.                 Throw New ArgumentException("Invalid property name")
  128.             End If
  129.  
  130.             If parts.Length = 1 OrElse _
  131.                parts(1) = String.Empty OrElse _
  132.                String.Compare(parts(1), "ASC", True) = 0 Then
  133.                 direction = ListSortDirection.Ascending
  134.             ElseIf String.Compare(parts(1), "DESC", True) = 0 Then
  135.                 direction = ListSortDirection.Descending
  136.             Else
  137.                 Throw New ArgumentException("Invalid sort direction")
  138.             End If
  139.         End If
  140.     End Sub
  141. #End Region 'Methods
  142.  
  143. #Region "Serialization"
  144.     Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
  145.         ' This gets the data without error.
  146.         ' The list contains the correct number of items,
  147.         ' but each item is Nothing.
  148.         Dim data As List(Of FGSData) = info.GetValue("FGSData", GetType(List(Of FGSData)))
  149.         For Each fgs As FGSData In data
  150.             Me.Add(fgs)
  151.         Next
  152.  
  153.         ' I think I want to do this, but Me.Items is read only
  154.         'Me.Items = info.GetValue("FGSData", GetType(List(Of FGSData)))
  155.  
  156.         ' Ultimately, this is the part that is giving me problems.
  157.     End Sub
  158.  
  159.     Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
  160.         info.AddValue("FGSData", Me.Items)
  161.     End Sub
  162. #End Region 'Serialization
  163. End Class