By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,269 Members | 1,507 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,269 IT Pros & Developers. It's quick & easy.

Sorting a System.Collections.ObjectModel.Collection

P: n/a
How do you sort a generic collection derived from
System.Collections.ObjectModel.Collection?

Thanks in advance,
- Arthur Dent
Mar 22 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
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

Mar 22 '06 #2

P: n/a
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.
"Pieter" <pi**********@hotmail.com> wrote in message
news:Ox**************@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


Mar 23 '06 #3

P: n/a
"Arthur Dent" <hi*********************@yahoo.com> wrote in message
news:%2****************@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.
Mar 24 '06 #4

P: n/a
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" <hi*********************@yahoo.com> wrote in message
news:eA**************@TK2MSFTNGP11.phx.gbl...
| How do you sort a generic collection derived from
| System.Collections.ObjectModel.Collection?
|
| Thanks in advance,
| - Arthur Dent
|
|
Mar 24 '06 #5

P: n/a
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]" <Ja************@tsbradley.net> wrote in
message news:eU**************@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" <hi*********************@yahoo.com> wrote in message
news:eA**************@TK2MSFTNGP11.phx.gbl...
| How do you sort a generic collection derived from
| System.Collections.ObjectModel.Collection?
|
| Thanks in advance,
| - Arthur Dent
|
|

Mar 25 '06 #6

P: n/a
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
"Arthur Dent" <hi*********************@yahoo.com> wrote in message
news:%2******************@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]" <Ja************@tsbradley.net> wrote in
| message news:eU**************@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" <hi*********************@yahoo.com> wrote in message
| > news:eA**************@TK2MSFTNGP11.phx.gbl...
| > | How do you sort a generic collection derived from
| > | System.Collections.ObjectModel.Collection?
| > |
| > | Thanks in advance,
| > | - Arthur Dent
| > |
| > |
| >
| >
|
|
Mar 25 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.