Sort using multiple properties?

Sort using multiple properties?

Old forum URL: forums.lhotka.net/forums/t/199.aspx


dnorth posted on Thursday, May 25, 2006

First off, I am relatively new to CSLA .NET, so if this question has been asked, and addressed many times in the past, I apologize...

In CSLA .NET 2.0, I understand I can use SortedBindingList<T> to create a view of a collection, sorted by one property.  It appears CSLA .NET 1.x had a community contributed? class named SortedCollectionBase, which could be used to return a list, sorted by multiple properties?

What is considered "best practice" in CSLA .NET 2.0 when there is a need to sort a collection using multiple properties?

Chris replied on Thursday, May 25, 2006

Good question!  I was wondering the same thing when I read about the SortedBindingList.  I guess it would be possible to create another class or alter the existing one, but, that would defeat the purpose of having a more flexible class.

Chris

RockfordLhotka replied on Thursday, May 25, 2006

There is another interface (the name of which escapes me at the moment) that Microsoft added in .NET 2.0 to support more advanced sorting and so forth. I simply didn't have time to research and implement that interface while writing the book.

The real point of complexity is that multi-column sorts require a sorting algorithm that doesn't disrupt the overall ordering of the list. There's a technical term for this too, which escapes me at the moment, but it is a very serious limitation on how you can do your sorting. I don't know that the Sort() method on the list object works this way, and if it doesn't it would mean writing a new sorting algorithm that does meet this requirement.

Chris replied on Thursday, May 25, 2006

Rocky,

Don't get me wrong ... the SortedBindingList is AWESOME!  I read through it twice and told others how cool it was how you put a wrapper on the original IList.  If the need for sorting by multiple properties arises, I know now to look for that other interface and keep in mind that another algorithm is required.  Thanks for your response.

Chris

Vaxman2 replied on Thursday, May 25, 2006

RockfordLhotka:

The real point of complexity is that multi-column sorts require a sorting algorithm that doesn't disrupt the overall ordering of the list. There's a technical term for this too, which escapes me at the moment,

Were you looking for the term "stable sorting"?

trevstar replied on Thursday, May 25, 2006

Rocky,
Are you referring to the IBindingListView?  I saw this when looking for a multi-property sorting solution a while ago, and was hoping it would appear in CSLA 2.0.  It didn't appear...and you fell off the pedestal I previously had you on!  Wink [;)]

Here's the link to the documentation, but I haven't had a chance to start implementing it yet.
http://msdn2.microsoft.com/en-us/library/system.componentmodel.ibindinglistview.aspx

BTW, thanks for all the work on CSLA 2.  It's incredibly well thought out, and I'm anxious to try it out on my next project.  I'm blown away by many things, but I especially like the new validation and authorization rules you've added.

RockfordLhotka replied on Thursday, May 25, 2006

Yes, stable sorting and IBindingListView - thanks! I was very blurry this morning - I got in from Seattle late last night (the temporary end to several weeks of contiguous travel) - and my brain wasn't firing on all cylinders... Tongue Tied [:S]

dnorth replied on Thursday, May 25, 2006

All,

Thanks for the quick response!  Your ideas have given me something to learn more about.

Rocky,

Thanks for sharing  CSLA .NET with us.  It's helping me solve some interesting problems... For example, the Infragistics NetAdvantage UltraGrid control _bogs_ down when sorting even a single string-based column when there are a significant number of rows in the grid.  However, by taking advantage of the fact that they support before/after sort change events, I was able to use a SortedBindingList, based on the clicked column header key, to quickly create a new view on my collection -- the performance difference is amazing.

David      

hurcane replied on Thursday, May 25, 2006

To implement a multi-column sort, would this simple technique work?

Replace the SortProperty field with a SortProperty list. Each entry in the list specifies property and sort direction. The list is in order of importance.

The CompareTo method is implemented sorta like this:

Public Function CompareTo(byval obj As Object) As Integer
dim i as Integer = 0
dim PropertyToCompare as String
dim SortDirection as ListSortDirection
do
PropertyToCompare = PropertyList(i).PropertyName
SortDirection = PropertyList(i).SortDirection
' TODO: Use reflection to get property value from Me (myProperty) and obj (objProperty).
i += 1
loop while i < PropertyList.Count AndAlso myProperty.Equals(objProperty)

' At this point, we're positioned on a property that either isn't equal,
' or we're on the last property. Regardless, we can
' return the comparable state.
If SortDirection = Ascending Then
Return MyProperty.CompareTo(objProperty)
Else
Return -1 * MyProperty.CompareTo(objProperty)
End Function

This code is just off the top of my head, but I think the algorithm is sound. If I had a property list of {State, City, Name}, this mult-column sort effectively works like "grouping" sections on reports. All Alabama records would show, with the records inside Alabama sorted by City, and all records in Birmingham would be sorted by Name.

I call this technique simple. Looking back at it, perhaps it is a little bit complex. I used a String for the PropertyName, but the interface uses a PropertyDescriptor object, which actually makes the Reflection part a little easier.

The SortedBindingList already does most of the work.

DansDreams replied on Friday, May 26, 2006

I think the point of mentioning IBindingListView is that you'd probably want to implement that to support standard Microsoft behavior.  Internally you gotta do what you gotta do, but I think it's valuable to look as standard as possible to the "public".

glenntoy replied on Thursday, June 01, 2006

Hi guys,

I was also looking on how to sort a ReadOnlyList with multiple properties. Then, I tried searching for more information about IBindingListView and I guess I found one resource that has also an example in C# buts its not binding CSLA objects.

The book I'm referring was Data Binding with Windows Forms 2.0: Prorgamming Smart Client Data Applications with .NET by Brian Noyes

So I tried, using his BindingListView to sort my ReadOnlyList but I didn't have the luck n doing it because he was using generic list and I'm quiet a newbie with regards to the behavior of data binding.

So what I did in my case is to create a generic list of my ReadOnlyBase (e.g. Dim gl as new List(Of MyReadOnlyBase) and manualy implementing the fetching of records.

Then I use that authors BindingListView and it works. I haven't tried using it in a grid. I'm doing this for reporting. I dont know this will be efficient enough i'll try to test it more.

 

 

 

SonOfPirate replied on Thursday, June 01, 2006

If I'm not mistaken, it is the intent of the IComparable interface to provide support for sorting lists and I believe base functionality provided in some places in the framework defers to this interface when performing such sort operations.  In the previous version of our framework (based on CSLA), we implemented this interface on our base objects and applied the more complicated, multi-level sort criteria within the CompareTo method.  For instance, a simple example would be:

public System.Int32 CompareTo(T other)
{
    System.Int32 retVal = this.LastName.CompareTo(other.LastName);
    if (retVal == 0)
    {
        retVal = this.FirstName.CompareTo(other.FirstName);
        if (retVal == 0)
            retVal = this.MiddleInitial.CompareTo(other.MiddleInitial);
    }
    return retVal;
}

I liked this approach because it encapsulated the comparison logic within the object itself and the sort process within the collections could be left 'generic'.  However, this doesn't help if you want to allow users to dynamically sort columns in a table or grid.  In those cases, I've had the control handle the sorting (actually deferred to a Sorter class that could be used by multiple controls).

This is pretty rudimentary and may not fit within better performing approaches, so I am anxious to see what everyone else posts as a solution.

 

Aztec_2Step replied on Thursday, March 20, 2008

I saw a previous link where "S.E. Michigan" suggested overloading the ApplySort method with a parameter IComparer. I have not seen any code on how to do this downstream from the initial overload so I was wondering if it would help to request something like that posted here.

The problem I see with implementing the IComparable interface on a SubClass is that it provided one way (the default way) to sort that type of item. I we could provide the IComparer then there are infinite ways to sort depending on how bad our OCD is that day... Anyway, I think down stream of the ApplySort() is a private method DoSort() which calls sort on an internal list of ???SortedBindingList<T>.ListItem which I don't know how to create a IComparer<SortedBindingList<T>.ListItem> since ListItem is private or protected and I don't want to change that...

Anyway, If anyone had some code I could use or tweak, I would greatly appreciate it!!! Please email to: Aztec_2Step ( @ ) hotmail.com

 

RockfordLhotka replied on Sunday, March 23, 2008

To take a totally different look at it, a very simple solution (if possible) is to upgrade to .NET 3.5 and use LINQ.

CSLA 3.5 includes SortedBindingList and FilteredBindingList, but I now consider them depricated because they are rather pointless now that LINQ has arrived and CSLA includes "LINQ to CSLA" functionality.

Copyright (c) Marimer LLC