Solved

Sorting BindableList Base class

Posted on 2008-10-15
1
852 Views
Last Modified: 2013-11-07
This is not sorting correctly. Can anyone help me fix it?

Code below shows:
Business Object- clsPerson
BaseClass for Business Object Collection- clsBindingListBase
Business Object Collection.- clsPersons
PropertyComparer class- PropertyComparer

At the end of the code, the is the webform code that demonstrate's my use and there I comment what I expect and what I get.

Some of this I've pieced together from lots of reading of posts and thought I had it, but something's wrong. PS I want to use a base cass for the collection because I'll be creating lots of collections in my project and want to inherit the common functionality.

Thanks, Jeff

'''''''''''''''''''''''''''''''''
''''' Business Object Class '''''
'''''''''''''''''''''''''''''''''
Public Class clsPerson
    Private _Id As Integer
    Private _Name As String
    Public ReadOnly Property Id() As Integer
        Get
            Return _Id
        End Get
    End Property
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property
    Public Sub New(ByVal Name As String, ByVal Id As Integer)
        _Id = Id
        _Name = Name
    End Sub
End Class
 
''''''''''''''''''''''''''''''''''''''''''''
''''' Base class for object collection '''''
''''''''''''''''''''''''''''''''''''''''''''
Imports System.ComponentModel
Public Class clsBindingListBase(Of T)
    Inherits BindingList(Of T)
    Implements IEnumerable
 
    Private _isSorted As Boolean
 
    Protected Overloads Overrides ReadOnly Property SupportsSortingCore() As _
                                                                       Boolean
        Get
            Return True
        End Get
    End Property
    Protected Overloads Overrides Sub ApplySortCore(ByVal [property] As _ 
                      PropertyDescriptor, ByVal direction As ListSortDirection)
 
        ' Get list to sort 
        Dim items As List(Of T) = TryCast(Me.Items, List(Of T))
 
        ' Apply and set the sort, if items to sort 
        If items IsNot Nothing Then
            Dim pc As New PropertyComparer(Of T)([property], direction)
            items.Sort(pc)
            _isSorted = True
        Else
            _isSorted = False
        End If
        ' Let bound controls know they should refresh their views 
        Me.OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
    End Sub
    Protected Overloads Overrides ReadOnly Property IsSortedCore() As Boolean
        Get
            Return _isSorted
        End Get
    End Property
    Protected Overloads Overrides Sub RemoveSortCore()
        _isSorted = False
    End Sub
End Class
 
''''''''''''''''''''''''''''''''''''''''''''
''''' Business Object Collection Class '''''
''''''''''''''''''''''''''''''''''''''''''''
Imports System.ComponentModel
 
Public Class clsPersons
    Inherits clsBindingListBase(Of clsPerson)
    Protected Overloads Overrides Sub ApplySortCore(ByVal [property] As _
                      PropertyDescriptor, ByVal direction As ListSortDirection)
        Dim items As List(Of clsPerson) = TryCast(Me.Items, List(Of clsPerson))
        Dim pc As New PropertyComparer(Of clsPerson)([property], direction)
        items.Sort(pc)
    End Sub
 
    Public Sub SortByName(ByVal direction As ListSortDirection)
        Dim propDescriptors As PropertyDescriptorCollection = _ 
                            TypeDescriptor.GetProperties(GetType(clsPerson))
        Me.ApplySortCore(propDescriptors("Name"), direction)
    End Sub
 
    Public Sub SortById(ByVal direction As ListSortDirection)
        Dim propDescriptors As PropertyDescriptorCollection = _ 
                            TypeDescriptor.GetProperties(GetType(clsPerson))
        Me.ApplySortCore(propDescriptors("Id"), direction)
    End Sub
End Class
 
'''''''''''''''''''''''''''
'''' Property Comparer ''''
'''''''''''''''''''''''''''
Imports System
Imports System.ComponentModel
Imports System.Collections.Generic
Imports System.Reflection
 
Public Class PropertyComparer(Of T)
    Implements System.Collections.Generic.IComparer(Of T)
    Private _property As PropertyDescriptor
    Private _direction As ListSortDirection
 
    Public Sub New(ByVal [property] As PropertyDescriptor, ByVal direction As _
                                                             ListSortDirection)
        _property = [property]
        _direction = direction
    End Sub
 
#Region "IComparer"
 
    Public Function Compare(ByVal xWord As T, ByVal yWord As T) As Integer
        ' Get property values 
        Dim xValue As Object = GetPropertyValue(xWord, _property.Name)
        Dim yValue As Object = GetPropertyValue(yWord, _property.Name)
 
        ' Determine sort order 
        If _direction = ListSortDirection.Ascending Then
            Return CompareAscending(xValue, yValue)
        Else
            Return CompareDescending(xValue, yValue)
        End If
    End Function
 
    Public Shadows Function Equals(ByVal xWord As T, ByVal yWord As T) As _
                                                                     Boolean
        Return xWord.Equals(yWord)
    End Function
 
    Public Shadows Function GetHashCode(ByVal obj As T) As Integer
        Return obj.GetHashCode()
    End Function
 
#End Region
 
    ' Compare two property values of any type 
    Private Function CompareAscending(ByVal xValue As Object, ByVal yValue As _
                                                             Object) As Integer
        Dim result As Integer
 
        ' If values implement IComparer 
        If TypeOf xValue Is IComparable Then
            result = DirectCast(xValue, IComparable).CompareTo(yValue)
            ' If values don't implement IComparer but are equivalent 
        ElseIf xValue.Equals(yValue) Then
            result = 0
        Else
            ' Values don't implement IComparer and are not equivalent, so 
            ' compare as string values 
            result = xValue.ToString().CompareTo(yValue.ToString())
        End If
 
        ' Return result 
        Return result
    End Function
 
    Private Function CompareDescending(ByVal xValue As Object, _
                                            ByVal yValue As Object) As Integer
        ' Return result adjusted for ascending or descending sort order ie 
        ' multiplied by 1 for ascending or -1 for descending 
        Return CompareAscending(xValue, yValue) * -1
    End Function
 
    Private Function GetPropertyValue(ByVal value As T, ByVal [property] As _
                                                             String) As Object
        ' Get property 
        Dim propertyInfo As PropertyInfo = _
                                      value.[GetType]().GetProperty([property])
 
        ' Return value 
        Return propertyInfo.GetValue(value, Nothing)
    End Function
 
    Public Function Compare1(ByVal x As T, ByVal y As T) As Integer _
            Implements System.Collections.Generic.IComparer(Of T).Compare
    End Function
End Class
 
'''''''''''''''''''''
''''' Form Code '''''
'''''''''''''''''''''
Dim Persons As New clsPersons
Persons.Add(New clsPerson("Jeff", "1"))
Persons.Add(New clsPerson("Lezlie", "3"))
Persons.Add(New clsPerson("Frank", "2"))
 
Response.Write("Default Order:")
For Each Person As clsPerson In Persons
    Response.Write(Person.Id & "-" & Person.Name & ", ")
Next
 
' I would expect to get below "1-Jeff, 2-Frank, 3-Lezlie"
' Instead I get below "2-Frank, 3-Lezlie, 1-Jeff"
Response.Write("Asending Order:")
Persons.SortById(ComponentModel.ListSortDirection.Ascending)
For Each Person As clsPerson In Persons
    Response.Write(Person.Id & "-" & Person.Name & ", ")
Next
 
' I would expect to get below "3-Lezlie, 2-Frank, 1-Jeff"
' Instead I get below "1-Jeff, 3-Lezlie, 2-Frank"
Response.Write("Desending Order:")
Persons.SortById(ComponentModel.ListSortDirection.Descending)
 
For Each Person As clsPerson In Persons
    Response.Write(Person.Id & "-" & Person.Name & ", ")
Next

Open in new window

0
Comment
Question by:JEFFCECCHINI
1 Comment
 

Accepted Solution

by:
JEFFCECCHINI earned 0 total points
ID: 22751164
After hours of searching I found something that worked for me...

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=20010&SiteID=1
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question