Home All Groups Group Topic Archive Search About

Sorting a System.Collections.ObjectModel.Collection

Author
22 Mar 2006 2:51 AM
Arthur Dent
How do you sort a generic collection derived from
System.Collections.ObjectModel.Collection?

Thanks in advance,
- Arthur Dent

Author
22 Mar 2006 9:14 AM
Pieter
Hi,

I made this Generic 'base' List that I use to store collections of objects.
It allows me to sort them, show them in a datagrid/datagridview, search on
propertys, and some stuff to save all the items in the class, see if they
have changes etc. Just pick out the things you need :-)

I hope this helps.

Pieter

Option Explicit On

Imports System.Windows.Forms

Imports System.ComponentModel
Imports System.Collections
Imports System.Collections.Specialized

Public Class clsBaseList(Of T As clsBaseClass)
    Inherits BindingList(Of T)
    Implements IComponent

    Public Sub New()
        MyBase.New()
        Me.AllowNew = False
        Me.AllowRemove = True
    End Sub

#Region "IComponent Implementation"
    Private m_Site As ISite = Nothing
    Public Event Disposed(ByVal sender As Object, ByVal e As
System.EventArgs) _
        Implements System.ComponentModel.IComponent.Disposed

    Protected Property Site() As System.ComponentModel.ISite Implements _
        System.ComponentModel.IComponent.Site
        Get
            Return m_Site
        End Get
        Set(ByVal Value As System.ComponentModel.ISite)
            m_Site = Value
        End Set
    End Property

    Public Sub Dispose() Implements System.IDisposable.Dispose
        Me.Items.Clear()
        RaiseEvent Disposed(Me, System.EventArgs.Empty)
    End Sub
#End Region

#Region "IBindingList Sorting Features"
    Private m_SupportsSorting As Boolean = True
    Private m_SortProperty As PropertyDescriptor
    Private m_SortDirection As ListSortDirection
    Private m_OriginalList As ArrayList

    Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
        Get
            Return m_SupportsSorting
        End Get
    End Property
    Protected Overrides ReadOnly Property SortDirectionCore() As
System.ComponentModel.ListSortDirection
        Get
            Return m_SortDirection
        End Get
    End Property

    Protected Overrides ReadOnly Property SortPropertyCore() As
System.ComponentModel.PropertyDescriptor
        Get
            Return m_SortProperty
        End Get
    End Property

    Protected Overrides ReadOnly Property IsSortedCore() As Boolean
        Get
            Return m_SortProperty Is Nothing
        End Get
    End Property

    Private Sub SaveList()
        m_OriginalList = New ArrayList(Me.Items)
    End Sub

    Private Sub ResetList(ByVal NewList As ArrayList)
        Me.ClearItems()
        For Each m_T As T In NewList
            Me.Add(m_T)
        Next
    End Sub

    Private Sub DoSort()
        Dim m_Comparer As New clsListComparer(m_SortProperty,
m_SortDirection)
        Dim m_SortList As New ArrayList(Me.Items)
        m_SortList.Sort(m_Comparer)
        ResetList(m_SortList)
    End Sub

    Protected Overrides Sub ApplySortCore(ByVal prop As
System.ComponentModel.PropertyDescriptor, ByVal direction As
System.ComponentModel.ListSortDirection)
        'toegevoegd door Pieter want sorteerde enkel Ascending in een
DataGridView...
        If m_SortProperty IsNot Nothing Then
            If (m_SortProperty.Name = prop.Name) And (m_SortDirection =
direction) Then
                'wisselen!
                direction = (direction + 1) Mod 2
            End If
        End If

        m_SortProperty = prop
        m_SortDirection = direction
        If (m_OriginalList Is Nothing) Then
            SaveList()
        End If
        DoSort()
    End Sub

    Protected Overrides Sub RemoveSortCore()
        ResetList(m_OriginalList)
        m_SortDirection = Nothing
        m_SortProperty = Nothing
    End Sub
#End Region

#Region "Private Variabel Declarations"
    Private m_blnSavedSuccesfull As Boolean
    Private m_blnDeletedSuccesfull As Boolean
    Private m_blnCatchChanges As Boolean = True
    Private m_blnHasChanges As Boolean = False
    Private m_strEntiteName As String = "entité"
    Private m_strEntiteCe As String = "cette"
    Private m_blnSelected As Boolean = True
    Private m_blnFilling As Boolean = False
    Private m_blnThrowEveryChangesEvent As Boolean = False
#End Region

#Region "Protected Variabel Declarations"

#End Region

#Region "Protected Methods"
    ''' <name>Sub SaveBegin</name>
    ''' <summary>
    ''' Method to call at the beginning of a Save.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Protected Sub SaveBegin()
        Me.SavedSuccesfull = True
    End Sub

    ''' <name>Sub SaveEnd</name>
    ''' <summary>
    ''' Method to call at the end of a Save. Calls
SetClassToUnchangedState(). Must only be called on SavedSuccesfull.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Protected Sub SaveEnd()
        If Me.SavedSuccesfull Then
            'Après qu'on a sauvegarder tout les info: donne la message qu'on
a tout bien sauvegarder et qu'on peut remttre le control dans un état "pas
de changements"
            SetCollectionToUnchangedState()
        Else
            'tell the user that his class wasn't saved succesfully!
        End If
        'raise the event that the save has ended
        'RaiseEvent SaveHasEnded(Me, EventArgs.Empty)
    End Sub

    ''' <name>Sub DeleteBegin</name>
    ''' <summary>
    ''' Method to call at the beginning of a Delete.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Protected Sub DeleteBegin()
        Me.DeletedSuccesfull = True
    End Sub
#End Region

#Region "Public Propertys"
    ''' <name>Property SavedSuccesfull</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Indique si la classe a été sauvegarder avec succès.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property SavedSuccesfull() As Boolean
        Get
            Return m_blnSavedSuccesfull
        End Get
        Set(ByVal value As Boolean)
            m_blnSavedSuccesfull = value
        End Set
    End Property

    ''' <name>Property DeletedSuccesfull</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Indique si la classe a été supprimé avec succès.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property DeletedSuccesfull() As Boolean
        Get
            Return m_blnDeletedSuccesfull
        End Get
        Set(ByVal value As Boolean)
            m_blnDeletedSuccesfull = value
        End Set
    End Property

    ''' <name>Property CatchChanges</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Indique si le control doit réagir sur des changements ou pas: par
exemple pas pendant qu'on fait le load d'une entité...
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property CatchChanges() As Boolean
        Get
            Return m_blnCatchChanges
        End Get
        Set(ByVal value As Boolean)
            m_blnCatchChanges = value
            Dim clsI As clsBaseClass
            For Each clsI In MyBase.Items
                clsI.CatchChanges = m_blnCatchChanges
            Next
        End Set
    End Property

    ''' <name>Property ThrowEveryChangesEvent</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Indique qu'un evenement doit être raised à chaque changement, ou
seulement le premier fois...
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property ThrowEveryChangesEvent() As Boolean
        Get
            Return m_blnThrowEveryChangesEvent
        End Get
        Set(ByVal value As Boolean)
            m_blnThrowEveryChangesEvent = value
        End Set
    End Property

    '<System.ComponentModel.DefaultValue(False)> _
    Public Event HasChangesEvent As EventHandler(Of HasChangesEventArgs)
    ''' <name>Property HasChanges</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' True s'il y a des changements qui se sont passés aux propertys de la
classe.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property HasChanges() As Boolean
        Get
            Return m_blnHasChanges
        End Get
        Set(ByVal value As Boolean)
            m_blnHasChanges = value
        End Set
    End Property

    ''' <name>Property EntiteName</name>
    ''' <returns>String</returns>
    ''' <summary>
    ''' Le nom de l'entité de la classe.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property EntiteName() As String
        Get
            Return m_strEntiteName
        End Get
        Set(ByVal value As String)
            m_strEntiteName = value
        End Set
    End Property

    ''' <name>Property EntiteCe</name>
    ''' <returns>String</returns>
    ''' <summary>
    ''' CET adresse, CE fournisseur, ...
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Property EntiteCe() As String
        Get
            Return m_strEntiteCe
        End Get
        Set(ByVal value As String)
            m_strEntiteCe = value
        End Set
    End Property

#End Region

#Region "Base Collection Methods"
    ''' <name>Function TestCloseCollection</name>
    ''' <returns>Integer</returns>
    ''' <summary>
    ''' This Methode tests for unsaved changes when CatchChanges is True,
and ask to save unchanged changes.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Function TestCloseCollection() As Integer
        If Me.m_blnCatchChanges And Me.m_blnHasChanges Then
            Dim intA As Integer
            intA = MessageBox.Show("Vous avez fait des changements depuis le
dernier sauvegarde." & vbCrLf & "Est-ce que vous voulez les sauvegarder?",
"Sauvegarder changements?", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Warning)

            If intA = vbYes Then
                'raise event to save the changes
                'RaiseEvent Click_Save()
                If Me.Save() Then
                    'if succesfully saved: class can be
disposed/finalized...
                    Return vbYes
                Else
                    'if not: don't close it...
                    Return vbCancel
                End If
            ElseIf intA = vbNo Then
                'if they don't want to save the changes: disable the
changes-handler
                Me.CatchChanges = False
                Return intA
            Else
                Return intA
            End If
        Else
            Return vbYes
        End If
    End Function

    ''' <name>Function Save</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' ' Update les changements ou insert les dans la base de données pour
tout les objets dans la collection.
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Function Save() As Boolean
        Try
            Me.SaveBegin()
            Dim clsI As clsBaseClass
            For Each clsI In MyBase.Items
                If Not clsI.Save() Then SavedSuccesfull = False
            Next
        Catch ex As Exception
            'ErrorMessage(ex)
            SavedSuccesfull = False
            Throw ex
        End Try

        Me.SaveEnd()
        Return SavedSuccesfull
    End Function

    ''' <name>Function Delete</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Supprime tout les éléments dans la liste
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Function Delete() As Boolean
        Try
            Me.DeleteBegin()
            Dim clsI As clsBaseClass
            For Each clsI In MyBase.Items
                If Not clsI.Delete Then
                    Me.DeletedSuccesfull = False
                    Return Me.DeletedSuccesfull
                    Exit Function
                End If
            Next

            'remove them all
            Me.Clear()
        Catch ex As Exception
            'ErrorMessage(ex)
            Me.DeletedSuccesfull = False
            Throw ex
        End Try

        Return Me.DeletedSuccesfull
    End Function

    ''' <name>Function Delete</name>
    ''' <returns>Boolean</returns>
    ''' <summary>
    ''' Deletes a specified Object in the List
    ''' </summary>
    ''' <param name="item">ByVal item As T: The item that must be
deleted</param>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Function Delete(ByVal item As T) As Boolean
        Try
            Me.DeleteBegin()
            If Not item.Delete Then Me.DeletedSuccesfull = False
            Me.Remove(item)
        Catch ex As Exception
            'ErrorMessage(ex)
            Me.DeletedSuccesfull = False
            Throw ex
        End Try

        Return Me.DeletedSuccesfull
    End Function

    ''' <name>Sub SetCollectionToUnchangedState</name>
    ''' <summary>
    ''' Methode qui remets le HasChanges = False et CatchChanges = True
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public Sub SetCollectionToUnchangedState()
        'reset it
        CatchChanges = True
        HasChanges = False
    End Sub

    Private Sub OnObjectInListChangedHandler(ByVal sender As Object, ByVal e
As HasChangesEventArgs)
        'always...
        ''regarde si on n'as pas déjà fait...
        ''If (Not m_blnHasChanges) Then  'il y a une valeur qui est changé!
        ''ok, il y a une valeur changé
        HasChanges = True
        RaiseEvent HasChangesEvent(sender, e)
        ''End If
    End Sub

    Private Sub OnObjectInListSelectedChangedHandler(ByVal sender As Object,
ByVal e As HasChangesEventArgs)
        'always...
        RaiseEvent HasChangesSelectedEvent(sender, e)
    End Sub

    Public Event HasChangesSelectedEvent As EventHandler(Of
HasChangesEventArgs)

    ''' <name>ReadOnly Property SelectedCount()</name>
    ''' <returns>Integer</returns>
    ''' <summary>
    ''' Property qui retourne le nombre d'Items dans la collection qui a le
property Selected = True
    ''' </summary>
    ''' <history>
    '''   PCO Created
    ''' </history>
    Public ReadOnly Property SelectedCount() As Integer
        Get
            Dim clsB As clsBaseClass
            Dim intC As Integer = 0
            For Each clsB In MyBase.Items
                If clsB.Selected Then
                    intC += 1
                End If
            Next
            Return intC
        End Get
    End Property
#End Region

#Region "List Methods"
    Public Shadows Sub Add(ByVal item As T)
        item.SetClassToUnchangedState()
        AddHandler item.HasChangesEvent, AddressOf
OnObjectInListChangedHandler
        AddHandler item.SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
        MyBase.Add(item)
    End Sub

    Public Shadows Sub Insert(ByVal index As Integer, ByVal item As T)
        item.SetClassToUnchangedState()
        AddHandler item.HasChangesEvent, AddressOf
OnObjectInListChangedHandler
        AddHandler item.SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
        MyBase.Insert(index, item)
    End Sub

    Public Shadows Sub Clear()
        For Each item As clsBaseClass In Me
            RemoveHandler item.HasChangesEvent, AddressOf
OnObjectInListChangedHandler
            RemoveHandler item.SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
        Next
        MyBase.Clear()
    End Sub

    Public Shadows Function Remove(ByVal item As T) As Boolean
        RemoveHandler item.HasChangesEvent, AddressOf
OnObjectInListChangedHandler
        RemoveHandler item.SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
        Return MyBase.Remove(item)
    End Function

    Public Shadows Sub RemoveAt(ByVal index As Integer)
        RemoveHandler MyBase.Item(index).HasChangesEvent, AddressOf
OnObjectInListChangedHandler
        RemoveHandler MyBase.Item(index).SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
        MyBase.RemoveAt(index)
    End Sub

    'very important, otherwise it will return objects of clsBaseClass, and
not object of T...
    Default Public Shadows Property Item(ByVal index As Integer) As T
        Get
            Return MyBase.Item(index)
        End Get
        Set(ByVal value As T)
            AddHandler value.HasChangesEvent, AddressOf
OnObjectInListChangedHandler
            AddHandler value.SelectedChanged, AddressOf
OnObjectInListSelectedChangedHandler
            MyBase.Item(index) = value
        End Set
    End Property

#End Region

#Region "Searching"
    Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
        Get
            Return True
        End Get
    End Property

    ' Item property descriptor collection cache
    Dim pdc As PropertyDescriptorCollection = Nothing

    Protected Overrides Function FindCore(ByVal [property] As
PropertyDescriptor, ByVal key As Object) As Integer
        ' Specify search columns
        If ([property] Is Nothing) Then
            Return -1
        End If

        ' Get list to search
        Dim items As List(Of T) = Me.Items
        ' Traverse list for value
        For Each item As T In items
            ' Test column search value
            Dim value As String = CStr([property].GetValue(item))
            'If value is the search value, return the
            ' index of the data item
            If (CStr(key) = value) Then
                Return IndexOf(item)
            End If
        Next item
        Return -1
    End Function

    'ByVal [property] As PropertyDescriptor, ByVal key As Object
    Public Function FindItems(ByVal ColumnName As String, ByVal ColumnValue
As Object) As clsBaseList(Of T)
        Dim lst As New clsBaseList(Of T)
        Dim properties As PropertyDescriptorCollection
        Dim myProperty As PropertyDescriptor

        ' Specify search columns
        If (ColumnName Is Nothing) Then
            Return Nothing
        End If

        ' Get list to search
        Dim items As List(Of T) = Me.Items
        ' Traverse list for value
        For Each item As T In items
            properties = TypeDescriptor.GetProperties(item.GetType)
            myProperty = properties.Find(ColumnName, False)
            ' Test column search value
            Dim value As String = CStr(myProperty.GetValue(item))
            'If value is the search value, return the
            ' index of the data item
            If (CStr(ColumnValue) = value) Then
                lst.Add(item)
            End If
        Next item
        Return lst
    End Function

    Public Function FindItem(ByVal ColumnName As String, ByVal ColumnValue
As Object) As T
        Dim properties As PropertyDescriptorCollection =
TypeDescriptor.GetProperties(Me.Items(0).GetType)
        Dim myProperty As PropertyDescriptor = properties.Find(ColumnName,
False)
        Dim i As Integer = FindCore(myProperty, ColumnValue)
        If i = -1 Then
            Return Nothing
        Else
            Return Me.Item(i)
        End If
    End Function

    Public Function SumItems(ByVal ColumnName As String) As Decimal
        Dim properties As PropertyDescriptorCollection
        Dim myProperty As PropertyDescriptor

        ' Specify search columns
        If (ColumnName Is Nothing) Then
            Return Nothing
        End If

        ' Get list to search
        Dim items As List(Of T) = Me.Items
        ' Traverse list for value
        Dim decSum As Decimal = 0
        For Each item As T In items
            properties = TypeDescriptor.GetProperties(item.GetType)
            myProperty = properties.Find(ColumnName, False)
            'Dim value As String = CStr(myProperty.GetValue(item))
            decSum += CSng(myProperty.GetValue(item))
        Next item
        Return decSum
    End Function

#End Region

End Class

Public Class clsListComparer
    Implements IComparer

    Private m_SortList As ListSortDescriptionCollection

    Public Sub New(ByVal SortProperty As PropertyDescriptor, ByVal direction
As ListSortDirection)
        'Create a new list every time
        m_SortList = New ListSortDescriptionCollection(New
ListSortDescription() {New ListSortDescription(SortProperty, direction)})
    End Sub

    Public Sub New(ByVal SortList As ListSortDescriptionCollection)
        m_SortList = SortList
    End Sub

    Private Function CompareSingleProperty(ByVal x As clsBaseClass, ByVal y
As clsBaseClass, ByVal prop As PropertyDescriptor, ByVal direction As
ListSortDirection) As Integer
        Dim result As Integer = 0
        Dim directionModifier As Integer
        If (direction = ListSortDirection.Ascending) Then
            directionModifier = 1
        Else
            directionModifier = -1
        End If
        If (x Is Nothing) Then
            result = -1 * directionModifier
        ElseIf (y Is Nothing) Then
            result = 1 * directionModifier
        ElseIf (prop.GetValue(x) < prop.GetValue(y)) Then
            result = -1 * directionModifier
        ElseIf (prop.GetValue(x) > prop.GetValue(y)) Then
            result = 1 * directionModifier
        Else
            result = 0
        End If
        Return result
    End Function

    Private Function Compare(ByVal x As Object, ByVal y As Object) As
Integer _
        Implements System.Collections.IComparer.Compare
        Dim idx As Integer
        Dim result As Integer
        If (Not TypeOf x Is clsBaseClass) Then
            Throw New ArgumentException("Unexpected Argument.  Arguments
must be of Type ", "x")
        End If
        If (Not TypeOf y Is clsBaseClass) Then
            Throw New ArgumentException("Unexpected Argument.  Arguments
must be of Type ", "y")
        End If
        For idx = 0 To m_SortList.Count - 1
            result = CompareSingleProperty(x, y,
m_SortList(idx).PropertyDescriptor, m_SortList(idx).SortDirection)
            If (result <> 0) Then
                Exit For
            End If
        Next
        Return result
    End Function
End Class
Author
23 Mar 2006 2:52 PM
Arthur Dent
I could do that, but the thing is that that defeats the point of OO. I was
trying to take advantage of the generic collection as a base so i wouldnt
have to reinvent the wheel..... theres a lot of code involved in coding
collection classes.


Show quoteHide quote
"Pieter" <pietercou***@hotmail.com> wrote in message
news:OxBdGEZTGHA.4960@TK2MSFTNGP12.phx.gbl...
> Hi,
>
> I made this Generic 'base' List that I use to store collections of
> objects. It allows me to sort them, show them in a datagrid/datagridview,
> search on propertys, and some stuff to save all the items in the class,
> see if they have changes etc. Just pick out the things you need :-)
>
> I hope this helps.
>
> Pieter
>
> Option Explicit On
>
> Imports System.Windows.Forms
>
> Imports System.ComponentModel
> Imports System.Collections
> Imports System.Collections.Specialized
>
> Public Class clsBaseList(Of T As clsBaseClass)
>    Inherits BindingList(Of T)
>    Implements IComponent
>
>    Public Sub New()
>        MyBase.New()
>        Me.AllowNew = False
>        Me.AllowRemove = True
>    End Sub
>
> #Region "IComponent Implementation"
>    Private m_Site As ISite = Nothing
>    Public Event Disposed(ByVal sender As Object, ByVal e As
> System.EventArgs) _
>        Implements System.ComponentModel.IComponent.Disposed
>
>    Protected Property Site() As System.ComponentModel.ISite Implements _
>        System.ComponentModel.IComponent.Site
>        Get
>            Return m_Site
>        End Get
>        Set(ByVal Value As System.ComponentModel.ISite)
>            m_Site = Value
>        End Set
>    End Property
>
>    Public Sub Dispose() Implements System.IDisposable.Dispose
>        Me.Items.Clear()
>        RaiseEvent Disposed(Me, System.EventArgs.Empty)
>    End Sub
> #End Region
>
> #Region "IBindingList Sorting Features"
>    Private m_SupportsSorting As Boolean = True
>    Private m_SortProperty As PropertyDescriptor
>    Private m_SortDirection As ListSortDirection
>    Private m_OriginalList As ArrayList
>
>    Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
>        Get
>            Return m_SupportsSorting
>        End Get
>    End Property
>    Protected Overrides ReadOnly Property SortDirectionCore() As
> System.ComponentModel.ListSortDirection
>        Get
>            Return m_SortDirection
>        End Get
>    End Property
>
>    Protected Overrides ReadOnly Property SortPropertyCore() As
> System.ComponentModel.PropertyDescriptor
>        Get
>            Return m_SortProperty
>        End Get
>    End Property
>
>    Protected Overrides ReadOnly Property IsSortedCore() As Boolean
>        Get
>            Return m_SortProperty Is Nothing
>        End Get
>    End Property
>
>    Private Sub SaveList()
>        m_OriginalList = New ArrayList(Me.Items)
>    End Sub
>
>    Private Sub ResetList(ByVal NewList As ArrayList)
>        Me.ClearItems()
>        For Each m_T As T In NewList
>            Me.Add(m_T)
>        Next
>    End Sub
>
>    Private Sub DoSort()
>        Dim m_Comparer As New clsListComparer(m_SortProperty,
> m_SortDirection)
>        Dim m_SortList As New ArrayList(Me.Items)
>        m_SortList.Sort(m_Comparer)
>        ResetList(m_SortList)
>    End Sub
>
>    Protected Overrides Sub ApplySortCore(ByVal prop As
> System.ComponentModel.PropertyDescriptor, ByVal direction As
> System.ComponentModel.ListSortDirection)
>        'toegevoegd door Pieter want sorteerde enkel Ascending in een
> DataGridView...
>        If m_SortProperty IsNot Nothing Then
>            If (m_SortProperty.Name = prop.Name) And (m_SortDirection =
> direction) Then
>                'wisselen!
>                direction = (direction + 1) Mod 2
>            End If
>        End If
>
>        m_SortProperty = prop
>        m_SortDirection = direction
>        If (m_OriginalList Is Nothing) Then
>            SaveList()
>        End If
>        DoSort()
>    End Sub
>
>    Protected Overrides Sub RemoveSortCore()
>        ResetList(m_OriginalList)
>        m_SortDirection = Nothing
>        m_SortProperty = Nothing
>    End Sub
> #End Region
>
> #Region "Private Variabel Declarations"
>    Private m_blnSavedSuccesfull As Boolean
>    Private m_blnDeletedSuccesfull As Boolean
>    Private m_blnCatchChanges As Boolean = True
>    Private m_blnHasChanges As Boolean = False
>    Private m_strEntiteName As String = "entité"
>    Private m_strEntiteCe As String = "cette"
>    Private m_blnSelected As Boolean = True
>    Private m_blnFilling As Boolean = False
>    Private m_blnThrowEveryChangesEvent As Boolean = False
> #End Region
>
> #Region "Protected Variabel Declarations"
>
> #End Region
>
> #Region "Protected Methods"
>    ''' <name>Sub SaveBegin</name>
>    ''' <summary>
>    ''' Method to call at the beginning of a Save.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Protected Sub SaveBegin()
>        Me.SavedSuccesfull = True
>    End Sub
>
>    ''' <name>Sub SaveEnd</name>
>    ''' <summary>
>    ''' Method to call at the end of a Save. Calls
> SetClassToUnchangedState(). Must only be called on SavedSuccesfull.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Protected Sub SaveEnd()
>        If Me.SavedSuccesfull Then
>            'Après qu'on a sauvegarder tout les info: donne la message
> qu'on a tout bien sauvegarder et qu'on peut remttre le control dans un
> état "pas de changements"
>            SetCollectionToUnchangedState()
>        Else
>            'tell the user that his class wasn't saved succesfully!
>        End If
>        'raise the event that the save has ended
>        'RaiseEvent SaveHasEnded(Me, EventArgs.Empty)
>    End Sub
>
>    ''' <name>Sub DeleteBegin</name>
>    ''' <summary>
>    ''' Method to call at the beginning of a Delete.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Protected Sub DeleteBegin()
>        Me.DeletedSuccesfull = True
>    End Sub
> #End Region
>
> #Region "Public Propertys"
>    ''' <name>Property SavedSuccesfull</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Indique si la classe a été sauvegarder avec succès.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property SavedSuccesfull() As Boolean
>        Get
>            Return m_blnSavedSuccesfull
>        End Get
>        Set(ByVal value As Boolean)
>            m_blnSavedSuccesfull = value
>        End Set
>    End Property
>
>    ''' <name>Property DeletedSuccesfull</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Indique si la classe a été supprimé avec succès.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property DeletedSuccesfull() As Boolean
>        Get
>            Return m_blnDeletedSuccesfull
>        End Get
>        Set(ByVal value As Boolean)
>            m_blnDeletedSuccesfull = value
>        End Set
>    End Property
>
>    ''' <name>Property CatchChanges</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Indique si le control doit réagir sur des changements ou pas: par
> exemple pas pendant qu'on fait le load d'une entité...
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property CatchChanges() As Boolean
>        Get
>            Return m_blnCatchChanges
>        End Get
>        Set(ByVal value As Boolean)
>            m_blnCatchChanges = value
>            Dim clsI As clsBaseClass
>            For Each clsI In MyBase.Items
>                clsI.CatchChanges = m_blnCatchChanges
>            Next
>        End Set
>    End Property
>
>    ''' <name>Property ThrowEveryChangesEvent</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Indique qu'un evenement doit être raised à chaque changement, ou
> seulement le premier fois...
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property ThrowEveryChangesEvent() As Boolean
>        Get
>            Return m_blnThrowEveryChangesEvent
>        End Get
>        Set(ByVal value As Boolean)
>            m_blnThrowEveryChangesEvent = value
>        End Set
>    End Property
>
>    '<System.ComponentModel.DefaultValue(False)> _
>    Public Event HasChangesEvent As EventHandler(Of HasChangesEventArgs)
>    ''' <name>Property HasChanges</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' True s'il y a des changements qui se sont passés aux propertys de
> la classe.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property HasChanges() As Boolean
>        Get
>            Return m_blnHasChanges
>        End Get
>        Set(ByVal value As Boolean)
>            m_blnHasChanges = value
>        End Set
>    End Property
>
>    ''' <name>Property EntiteName</name>
>    ''' <returns>String</returns>
>    ''' <summary>
>    ''' Le nom de l'entité de la classe.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property EntiteName() As String
>        Get
>            Return m_strEntiteName
>        End Get
>        Set(ByVal value As String)
>            m_strEntiteName = value
>        End Set
>    End Property
>
>    ''' <name>Property EntiteCe</name>
>    ''' <returns>String</returns>
>    ''' <summary>
>    ''' CET adresse, CE fournisseur, ...
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Property EntiteCe() As String
>        Get
>            Return m_strEntiteCe
>        End Get
>        Set(ByVal value As String)
>            m_strEntiteCe = value
>        End Set
>    End Property
>
> #End Region
>
> #Region "Base Collection Methods"
>    ''' <name>Function TestCloseCollection</name>
>    ''' <returns>Integer</returns>
>    ''' <summary>
>    ''' This Methode tests for unsaved changes when CatchChanges is True,
> and ask to save unchanged changes.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Function TestCloseCollection() As Integer
>        If Me.m_blnCatchChanges And Me.m_blnHasChanges Then
>            Dim intA As Integer
>            intA = MessageBox.Show("Vous avez fait des changements depuis
> le dernier sauvegarde." & vbCrLf & "Est-ce que vous voulez les
> sauvegarder?", "Sauvegarder changements?", MessageBoxButtons.YesNoCancel,
> MessageBoxIcon.Warning)
>
>            If intA = vbYes Then
>                'raise event to save the changes
>                'RaiseEvent Click_Save()
>                If Me.Save() Then
>                    'if succesfully saved: class can be
> disposed/finalized...
>                    Return vbYes
>                Else
>                    'if not: don't close it...
>                    Return vbCancel
>                End If
>            ElseIf intA = vbNo Then
>                'if they don't want to save the changes: disable the
> changes-handler
>                Me.CatchChanges = False
>                Return intA
>            Else
>                Return intA
>            End If
>        Else
>            Return vbYes
>        End If
>    End Function
>
>    ''' <name>Function Save</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' ' Update les changements ou insert les dans la base de données pour
> tout les objets dans la collection.
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Function Save() As Boolean
>        Try
>            Me.SaveBegin()
>            Dim clsI As clsBaseClass
>            For Each clsI In MyBase.Items
>                If Not clsI.Save() Then SavedSuccesfull = False
>            Next
>        Catch ex As Exception
>            'ErrorMessage(ex)
>            SavedSuccesfull = False
>            Throw ex
>        End Try
>
>        Me.SaveEnd()
>        Return SavedSuccesfull
>    End Function
>
>    ''' <name>Function Delete</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Supprime tout les éléments dans la liste
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Function Delete() As Boolean
>        Try
>            Me.DeleteBegin()
>            Dim clsI As clsBaseClass
>            For Each clsI In MyBase.Items
>                If Not clsI.Delete Then
>                    Me.DeletedSuccesfull = False
>                    Return Me.DeletedSuccesfull
>                    Exit Function
>                End If
>            Next
>
>            'remove them all
>            Me.Clear()
>        Catch ex As Exception
>            'ErrorMessage(ex)
>            Me.DeletedSuccesfull = False
>            Throw ex
>        End Try
>
>        Return Me.DeletedSuccesfull
>    End Function
>
>    ''' <name>Function Delete</name>
>    ''' <returns>Boolean</returns>
>    ''' <summary>
>    ''' Deletes a specified Object in the List
>    ''' </summary>
>    ''' <param name="item">ByVal item As T: The item that must be
> deleted</param>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Function Delete(ByVal item As T) As Boolean
>        Try
>            Me.DeleteBegin()
>            If Not item.Delete Then Me.DeletedSuccesfull = False
>            Me.Remove(item)
>        Catch ex As Exception
>            'ErrorMessage(ex)
>            Me.DeletedSuccesfull = False
>            Throw ex
>        End Try
>
>        Return Me.DeletedSuccesfull
>    End Function
>
>    ''' <name>Sub SetCollectionToUnchangedState</name>
>    ''' <summary>
>    ''' Methode qui remets le HasChanges = False et CatchChanges = True
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public Sub SetCollectionToUnchangedState()
>        'reset it
>        CatchChanges = True
>        HasChanges = False
>    End Sub
>
>    Private Sub OnObjectInListChangedHandler(ByVal sender As Object, ByVal
> e As HasChangesEventArgs)
>        'always...
>        ''regarde si on n'as pas déjà fait...
>        ''If (Not m_blnHasChanges) Then  'il y a une valeur qui est changé!
>        ''ok, il y a une valeur changé
>        HasChanges = True
>        RaiseEvent HasChangesEvent(sender, e)
>        ''End If
>    End Sub
>
>    Private Sub OnObjectInListSelectedChangedHandler(ByVal sender As
> Object, ByVal e As HasChangesEventArgs)
>        'always...
>        RaiseEvent HasChangesSelectedEvent(sender, e)
>    End Sub
>
>    Public Event HasChangesSelectedEvent As EventHandler(Of
> HasChangesEventArgs)
>
>    ''' <name>ReadOnly Property SelectedCount()</name>
>    ''' <returns>Integer</returns>
>    ''' <summary>
>    ''' Property qui retourne le nombre d'Items dans la collection qui a le
> property Selected = True
>    ''' </summary>
>    ''' <history>
>    '''   PCO Created
>    ''' </history>
>    Public ReadOnly Property SelectedCount() As Integer
>        Get
>            Dim clsB As clsBaseClass
>            Dim intC As Integer = 0
>            For Each clsB In MyBase.Items
>                If clsB.Selected Then
>                    intC += 1
>                End If
>            Next
>            Return intC
>        End Get
>    End Property
> #End Region
>
> #Region "List Methods"
>    Public Shadows Sub Add(ByVal item As T)
>        item.SetClassToUnchangedState()
>        AddHandler item.HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>        AddHandler item.SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>        MyBase.Add(item)
>    End Sub
>
>    Public Shadows Sub Insert(ByVal index As Integer, ByVal item As T)
>        item.SetClassToUnchangedState()
>        AddHandler item.HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>        AddHandler item.SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>        MyBase.Insert(index, item)
>    End Sub
>
>    Public Shadows Sub Clear()
>        For Each item As clsBaseClass In Me
>            RemoveHandler item.HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>            RemoveHandler item.SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>        Next
>        MyBase.Clear()
>    End Sub
>
>    Public Shadows Function Remove(ByVal item As T) As Boolean
>        RemoveHandler item.HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>        RemoveHandler item.SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>        Return MyBase.Remove(item)
>    End Function
>
>    Public Shadows Sub RemoveAt(ByVal index As Integer)
>        RemoveHandler MyBase.Item(index).HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>        RemoveHandler MyBase.Item(index).SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>        MyBase.RemoveAt(index)
>    End Sub
>
>    'very important, otherwise it will return objects of clsBaseClass, and
> not object of T...
>    Default Public Shadows Property Item(ByVal index As Integer) As T
>        Get
>            Return MyBase.Item(index)
>        End Get
>        Set(ByVal value As T)
>            AddHandler value.HasChangesEvent, AddressOf
> OnObjectInListChangedHandler
>            AddHandler value.SelectedChanged, AddressOf
> OnObjectInListSelectedChangedHandler
>            MyBase.Item(index) = value
>        End Set
>    End Property
>
> #End Region
>
> #Region "Searching"
>    Protected Overrides ReadOnly Property SupportsSearchingCore() As
> Boolean
>        Get
>            Return True
>        End Get
>    End Property
>
>    ' Item property descriptor collection cache
>    Dim pdc As PropertyDescriptorCollection = Nothing
>
>    Protected Overrides Function FindCore(ByVal [property] As
> PropertyDescriptor, ByVal key As Object) As Integer
>        ' Specify search columns
>        If ([property] Is Nothing) Then
>            Return -1
>        End If
>
>        ' Get list to search
>        Dim items As List(Of T) = Me.Items
>        ' Traverse list for value
>        For Each item As T In items
>            ' Test column search value
>            Dim value As String = CStr([property].GetValue(item))
>            'If value is the search value, return the
>            ' index of the data item
>            If (CStr(key) = value) Then
>                Return IndexOf(item)
>            End If
>        Next item
>        Return -1
>    End Function
>
>    'ByVal [property] As PropertyDescriptor, ByVal key As Object
>    Public Function FindItems(ByVal ColumnName As String, ByVal ColumnValue
> As Object) As clsBaseList(Of T)
>        Dim lst As New clsBaseList(Of T)
>        Dim properties As PropertyDescriptorCollection
>        Dim myProperty As PropertyDescriptor
>
>        ' Specify search columns
>        If (ColumnName Is Nothing) Then
>            Return Nothing
>        End If
>
>        ' Get list to search
>        Dim items As List(Of T) = Me.Items
>        ' Traverse list for value
>        For Each item As T In items
>            properties = TypeDescriptor.GetProperties(item.GetType)
>            myProperty = properties.Find(ColumnName, False)
>            ' Test column search value
>            Dim value As String = CStr(myProperty.GetValue(item))
>            'If value is the search value, return the
>            ' index of the data item
>            If (CStr(ColumnValue) = value) Then
>                lst.Add(item)
>            End If
>        Next item
>        Return lst
>    End Function
>
>    Public Function FindItem(ByVal ColumnName As String, ByVal ColumnValue
> As Object) As T
>        Dim properties As PropertyDescriptorCollection =
> TypeDescriptor.GetProperties(Me.Items(0).GetType)
>        Dim myProperty As PropertyDescriptor = properties.Find(ColumnName,
> False)
>        Dim i As Integer = FindCore(myProperty, ColumnValue)
>        If i = -1 Then
>            Return Nothing
>        Else
>            Return Me.Item(i)
>        End If
>    End Function
>
>    Public Function SumItems(ByVal ColumnName As String) As Decimal
>        Dim properties As PropertyDescriptorCollection
>        Dim myProperty As PropertyDescriptor
>
>        ' Specify search columns
>        If (ColumnName Is Nothing) Then
>            Return Nothing
>        End If
>
>        ' Get list to search
>        Dim items As List(Of T) = Me.Items
>        ' Traverse list for value
>        Dim decSum As Decimal = 0
>        For Each item As T In items
>            properties = TypeDescriptor.GetProperties(item.GetType)
>            myProperty = properties.Find(ColumnName, False)
>            'Dim value As String = CStr(myProperty.GetValue(item))
>            decSum += CSng(myProperty.GetValue(item))
>        Next item
>        Return decSum
>    End Function
>
> #End Region
>
> End Class
>
> Public Class clsListComparer
>    Implements IComparer
>
>    Private m_SortList As ListSortDescriptionCollection
>
>    Public Sub New(ByVal SortProperty As PropertyDescriptor, ByVal
> direction As ListSortDirection)
>        'Create a new list every time
>        m_SortList = New ListSortDescriptionCollection(New
> ListSortDescription() {New ListSortDescription(SortProperty, direction)})
>    End Sub
>
>    Public Sub New(ByVal SortList As ListSortDescriptionCollection)
>        m_SortList = SortList
>    End Sub
>
>    Private Function CompareSingleProperty(ByVal x As clsBaseClass, ByVal y
> As clsBaseClass, ByVal prop As PropertyDescriptor, ByVal direction As
> ListSortDirection) As Integer
>        Dim result As Integer = 0
>        Dim directionModifier As Integer
>        If (direction = ListSortDirection.Ascending) Then
>            directionModifier = 1
>        Else
>            directionModifier = -1
>        End If
>        If (x Is Nothing) Then
>            result = -1 * directionModifier
>        ElseIf (y Is Nothing) Then
>            result = 1 * directionModifier
>        ElseIf (prop.GetValue(x) < prop.GetValue(y)) Then
>            result = -1 * directionModifier
>        ElseIf (prop.GetValue(x) > prop.GetValue(y)) Then
>            result = 1 * directionModifier
>        Else
>            result = 0
>        End If
>        Return result
>    End Function
>
>    Private Function Compare(ByVal x As Object, ByVal y As Object) As
> Integer _
>        Implements System.Collections.IComparer.Compare
>        Dim idx As Integer
>        Dim result As Integer
>        If (Not TypeOf x Is clsBaseClass) Then
>            Throw New ArgumentException("Unexpected Argument.  Arguments
> must be of Type ", "x")
>        End If
>        If (Not TypeOf y Is clsBaseClass) Then
>            Throw New ArgumentException("Unexpected Argument.  Arguments
> must be of Type ", "y")
>        End If
>        For idx = 0 To m_SortList.Count - 1
>            result = CompareSingleProperty(x, y,
> m_SortList(idx).PropertyDescriptor, m_SortList(idx).SortDirection)
>            If (result <> 0) Then
>                Exit For
>            End If
>        Next
>        Return result
>    End Function
> End Class
>
>
>
>
>
Author
24 Mar 2006 8:49 AM
Pieter
"Arthur Dent" <hitchhikersguideto-n***@yahoo.com> wrote in message
news:%23oMIjloTGHA.5468@TK2MSFTNGP14.phx.gbl...
>I could do that, but the thing is that that defeats the point of OO. I was
>trying to take advantage of the generic collection as a base so i wouldnt
>have to reinvent the wheel..... theres a lot of code involved in coding
>collection classes.

Well, that's exactly what I did: it is taken all the advantages of the
generic classes, it was a bit more difficult, but really worth it (I like
generics): as you can see: "Public Class clsBaseList(Of T As clsBaseClass)".
So I didn't reinvent the wheel here I think :)

Althoug, in my particular case all my objects inherit from clsBaseClass,
which handles a lot of common functionality for my objects.
Author
24 Mar 2006 1:26 PM
Jay B. Harlow [MVP - Outlook]
Arthur,
In addition to the other comments:


Remember that Collection(Of T) is simply a wrapper for an object that
implements IList(Of T). This wrapped IList(Of T) does all the "heavy
lifting" the Collection(Of T) simply delegates to the wrapped IList(Of T).
<sidenote>Read Collection(Of T) uses the Strategy Pattern. The  IList(Of T)
is the strategy it uses to implement the list itself, by default its uses an
array like structure for the strategy (the List(Of T), you can easily
replace the strategy with a LinkedList or a Binary tree, see below for
details on replacing the strategy...</sidenote>

You can use Collection(Of T).Items to get at the wrapped IList(Of T).

By default Collection(Of T) uses a List(Of T) as the wrapped IList(Of T),
List(Of T) has a Sort method (plus a plethora of other methods).
Collection(Of T).Items is how you get at the wrapped IList(Of T). In other
words casting Collection(Of T).Items to List(Of T) should allow you to call
its Sort method.

Something like:

    Public Class Person
        Implements IComparable(Of Person)

        ...

        Public Function CompareTo(ByVal other As Person) As Integer
Implements System.IComparable(Of Person).CompareTo
            ...
        End Function

    End Class

    Public Class PersonCollection
        Inherits ObjectModel.Collection(Of Person)

        Public Sub Sort()
            DirectCast(Items, List(Of Person)).Sort()
        End Sub

    End Class

I would consider introducing a new generic collection base that incorporates
this sorting:

    Public Class CollectionBase(Of T)
        Inherits ObjectModel.Collection(Of T)

        Public Sub Sort()
            DirectCast(Items, List(Of T)).Sort()
        End Sub

        Public Sub Sort(ByVal comparer As IComparer(Of T))
            DirectCast(Items, List(Of T)).Sort(comparer)
        End Sub

        Public Sub Sort(ByVal index As Integer, ByVal count As Integer,
ByVal comparer As IComparer(Of T))
            DirectCast(Items, List(Of T)).Sort(index, count, comparer)
        End Sub

        Public Sub Sort(ByVal comparison As Comparison(Of T))
            DirectCast(Items, List(Of T)).Sort(comparison)
        End Sub

    End Class

Then PersonCollection would be based on this new base:

    Public Class PersonCollection
        Inherits CollectionBase(Of Person)

    End Class


NOTE: The above may fail if you call Collection(Of T).New(IList(Of T))
passing in a something other then List(Of T). For example:

    Public Class PersonCollection
        Inherits ObjectModel.Collection(Of Person)

        ' use a linked list strategy
        Public Sub New()
            MyBase.New(New LinkedList(Of Person))
        End Sub

        ' use an array strategy
        Public Sub New()
            MyBase.New(New Person(100-1) {}) ' base it on an 100 element
array
        End Sub

        ' use some other generic collection strategy
        ' where SpecializedCollection implements IList(Of T)
        Public Sub New()
            MyBase.New(New SpecializedCollection(Of Person))
        End Sub

    End Class

The Frameworks LinkedList(Of T) does not implement IList(Of T) although it
is easy to add. The array does work (as the wrapped list), giving you a
fixed sized collection that you cannot add or remove elements from (you can
only change existing entries)...

I have not yet posted my sample LinkedList(Of T) that implements IList(Of T)
to my web site...

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


Show quoteHide quote
"Arthur Dent" <hitchhikersguideto-n***@yahoo.com> wrote in message
news:eAOTJuVTGHA.1728@TK2MSFTNGP11.phx.gbl...
| How do you sort a generic collection derived from
| System.Collections.ObjectModel.Collection?
|
| Thanks in advance,
| - Arthur Dent
|
|
Author
25 Mar 2006 5:47 AM
Arthur Dent
Thank you, that was exactly what i was looking for, getting at the inner
list object to be able to use its methods.
Cheers!


Show quoteHide quote
"Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@tsbradley.net> wrote in
message news:eUytha0TGHA.2276@tk2msftngp13.phx.gbl...
> Arthur,
> In addition to the other comments:
>
>
> Remember that Collection(Of T) is simply a wrapper for an object that
> implements IList(Of T). This wrapped IList(Of T) does all the "heavy
> lifting" the Collection(Of T) simply delegates to the wrapped IList(Of T).
> <sidenote>Read Collection(Of T) uses the Strategy Pattern. The  IList(Of
> T)
> is the strategy it uses to implement the list itself, by default its uses
> an
> array like structure for the strategy (the List(Of T), you can easily
> replace the strategy with a LinkedList or a Binary tree, see below for
> details on replacing the strategy...</sidenote>
>
> You can use Collection(Of T).Items to get at the wrapped IList(Of T).
>
> By default Collection(Of T) uses a List(Of T) as the wrapped IList(Of T),
> List(Of T) has a Sort method (plus a plethora of other methods).
> Collection(Of T).Items is how you get at the wrapped IList(Of T). In other
> words casting Collection(Of T).Items to List(Of T) should allow you to
> call
> its Sort method.
>
> Something like:
>
>    Public Class Person
>        Implements IComparable(Of Person)
>
>        ...
>
>        Public Function CompareTo(ByVal other As Person) As Integer
> Implements System.IComparable(Of Person).CompareTo
>            ...
>        End Function
>
>    End Class
>
>    Public Class PersonCollection
>        Inherits ObjectModel.Collection(Of Person)
>
>        Public Sub Sort()
>            DirectCast(Items, List(Of Person)).Sort()
>        End Sub
>
>    End Class
>
> I would consider introducing a new generic collection base that
> incorporates
> this sorting:
>
>    Public Class CollectionBase(Of T)
>        Inherits ObjectModel.Collection(Of T)
>
>        Public Sub Sort()
>            DirectCast(Items, List(Of T)).Sort()
>        End Sub
>
>        Public Sub Sort(ByVal comparer As IComparer(Of T))
>            DirectCast(Items, List(Of T)).Sort(comparer)
>        End Sub
>
>        Public Sub Sort(ByVal index As Integer, ByVal count As Integer,
> ByVal comparer As IComparer(Of T))
>            DirectCast(Items, List(Of T)).Sort(index, count, comparer)
>        End Sub
>
>        Public Sub Sort(ByVal comparison As Comparison(Of T))
>            DirectCast(Items, List(Of T)).Sort(comparison)
>        End Sub
>
>    End Class
>
> Then PersonCollection would be based on this new base:
>
>    Public Class PersonCollection
>        Inherits CollectionBase(Of Person)
>
>    End Class
>
>
> NOTE: The above may fail if you call Collection(Of T).New(IList(Of T))
> passing in a something other then List(Of T). For example:
>
>    Public Class PersonCollection
>        Inherits ObjectModel.Collection(Of Person)
>
>        ' use a linked list strategy
>        Public Sub New()
>            MyBase.New(New LinkedList(Of Person))
>        End Sub
>
>        ' use an array strategy
>        Public Sub New()
>            MyBase.New(New Person(100-1) {}) ' base it on an 100 element
> array
>        End Sub
>
>        ' use some other generic collection strategy
>        ' where SpecializedCollection implements IList(Of T)
>        Public Sub New()
>            MyBase.New(New SpecializedCollection(Of Person))
>        End Sub
>
>    End Class
>
> The Frameworks LinkedList(Of T) does not implement IList(Of T) although it
> is easy to add. The array does work (as the wrapped list), giving you a
> fixed sized collection that you cannot add or remove elements from (you
> can
> only change existing entries)...
>
> I have not yet posted my sample LinkedList(Of T) that implements IList(Of
> T)
> to my web site...
>
> --
> Hope this helps
> Jay [MVP - Outlook]
> .NET Application Architect, Enthusiast, & Evangelist
> T.S. Bradley - http://www.tsbradley.net
>
>
> "Arthur Dent" <hitchhikersguideto-n***@yahoo.com> wrote in message
> news:eAOTJuVTGHA.1728@TK2MSFTNGP11.phx.gbl...
> | How do you sort a generic collection derived from
> | System.Collections.ObjectModel.Collection?
> |
> | Thanks in advance,
> | - Arthur Dent
> |
> |
>
>
Author
25 Mar 2006 3:23 PM
Jay B. Harlow [MVP - Outlook]
Arthur,

Thinking about it, it might be better to ensure that you have a wrapped
List(Of T) verses some other IList(Of T) collection... Especially when
introducing a new generic base class...

| >    Public Class CollectionBase(Of T)
| >        Inherits ObjectModel.Collection(Of T)
| >
            Public Sub New()
                MyBase.New()
            End Sub

            Public Sub New(list As IList(Of T))
                MyBase.New(list)
            End Sub

| >        Public Sub Sort()
                Dim list As List(Of T) = TryCast(Items, List(Of T))
                If list Is Nothing Then Throw New NotSupportedException()
                list.Sort()
| >        End Sub
| >

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


Show quoteHide quote
"Arthur Dent" <hitchhikersguideto-n***@yahoo.com> wrote in message
news:%23YskK%238TGHA.4540@TK2MSFTNGP10.phx.gbl...
| Thank you, that was exactly what i was looking for, getting at the inner
| list object to be able to use its methods.
| Cheers!
|
|
| "Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@tsbradley.net> wrote in
| message news:eUytha0TGHA.2276@tk2msftngp13.phx.gbl...
| > Arthur,
| > In addition to the other comments:
| >
| >
| > Remember that Collection(Of T) is simply a wrapper for an object that
| > implements IList(Of T). This wrapped IList(Of T) does all the "heavy
| > lifting" the Collection(Of T) simply delegates to the wrapped IList(Of
T).
| > <sidenote>Read Collection(Of T) uses the Strategy Pattern. The  IList(Of
| > T)
| > is the strategy it uses to implement the list itself, by default its
uses
| > an
| > array like structure for the strategy (the List(Of T), you can easily
| > replace the strategy with a LinkedList or a Binary tree, see below for
| > details on replacing the strategy...</sidenote>
| >
| > You can use Collection(Of T).Items to get at the wrapped IList(Of T).
| >
| > By default Collection(Of T) uses a List(Of T) as the wrapped IList(Of
T),
| > List(Of T) has a Sort method (plus a plethora of other methods).
| > Collection(Of T).Items is how you get at the wrapped IList(Of T). In
other
| > words casting Collection(Of T).Items to List(Of T) should allow you to
| > call
| > its Sort method.
| >
| > Something like:
| >
| >    Public Class Person
| >        Implements IComparable(Of Person)
| >
| >        ...
| >
| >        Public Function CompareTo(ByVal other As Person) As Integer
| > Implements System.IComparable(Of Person).CompareTo
| >            ...
| >        End Function
| >
| >    End Class
| >
| >    Public Class PersonCollection
| >        Inherits ObjectModel.Collection(Of Person)
| >
| >        Public Sub Sort()
| >            DirectCast(Items, List(Of Person)).Sort()
| >        End Sub
| >
| >    End Class
| >
| > I would consider introducing a new generic collection base that
| > incorporates
| > this sorting:
| >
| >    Public Class CollectionBase(Of T)
| >        Inherits ObjectModel.Collection(Of T)
| >
| >        Public Sub Sort()
| >            DirectCast(Items, List(Of T)).Sort()
| >        End Sub
| >
| >        Public Sub Sort(ByVal comparer As IComparer(Of T))
| >            DirectCast(Items, List(Of T)).Sort(comparer)
| >        End Sub
| >
| >        Public Sub Sort(ByVal index As Integer, ByVal count As Integer,
| > ByVal comparer As IComparer(Of T))
| >            DirectCast(Items, List(Of T)).Sort(index, count, comparer)
| >        End Sub
| >
| >        Public Sub Sort(ByVal comparison As Comparison(Of T))
| >            DirectCast(Items, List(Of T)).Sort(comparison)
| >        End Sub
| >
| >    End Class
| >
| > Then PersonCollection would be based on this new base:
| >
| >    Public Class PersonCollection
| >        Inherits CollectionBase(Of Person)
| >
| >    End Class
| >
| >
| > NOTE: The above may fail if you call Collection(Of T).New(IList(Of T))
| > passing in a something other then List(Of T). For example:
| >
| >    Public Class PersonCollection
| >        Inherits ObjectModel.Collection(Of Person)
| >
| >        ' use a linked list strategy
| >        Public Sub New()
| >            MyBase.New(New LinkedList(Of Person))
| >        End Sub
| >
| >        ' use an array strategy
| >        Public Sub New()
| >            MyBase.New(New Person(100-1) {}) ' base it on an 100 element
| > array
| >        End Sub
| >
| >        ' use some other generic collection strategy
| >        ' where SpecializedCollection implements IList(Of T)
| >        Public Sub New()
| >            MyBase.New(New SpecializedCollection(Of Person))
| >        End Sub
| >
| >    End Class
| >
| > The Frameworks LinkedList(Of T) does not implement IList(Of T) although
it
| > is easy to add. The array does work (as the wrapped list), giving you a
| > fixed sized collection that you cannot add or remove elements from (you
| > can
| > only change existing entries)...
| >
| > I have not yet posted my sample LinkedList(Of T) that implements
IList(Of
| > T)
| > to my web site...
| >
| > --
| > Hope this helps
| > Jay [MVP - Outlook]
| > .NET Application Architect, Enthusiast, & Evangelist
| > T.S. Bradley - http://www.tsbradley.net
| >
| >
| > "Arthur Dent" <hitchhikersguideto-n***@yahoo.com> wrote in message
| > news:eAOTJuVTGHA.1728@TK2MSFTNGP11.phx.gbl...
| > | How do you sort a generic collection derived from
| > | System.Collections.ObjectModel.Collection?
| > |
| > | Thanks in advance,
| > | - Arthur Dent
| > |
| > |
| >
| >
|
|