65.9K
CodeProject is changing. Read more.
Home

ListView Sorter

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.24/5 (13 votes)

Aug 7, 2002

viewsIcon

170901

downloadIcon

1444

Custom ListViewItemSorter with pluggable cell comparators

Introduction

My solution is an alternative to C# Sorted ListView, posted by Carlos H.Perez. The main difference is that I'm not trying to extend ListView control at all. Instead of that I suggest using a standard ListView with customizable ListViewSorter.

The main idea is to tie ListView column headers with appropriate delegates, which can handle column cells comparison activities. So I declare ListViewSorter.Comparer delegate, and enable to store column-delegate pairs into sorter.

//column cell comparer
public delegate int Comparer(string x, string y);
//comparer for column
public Comparer this[ColumnHeader _column] {...}

The sorter itself is tied to a list control and handles the ColumnClick events for that list. On each column the click sorter activates the clicked column.

//click handler
protected void Column_Click(object sender, ColumnClickEventArgs e)
{
    //get and verify clicked list
    ListView _list = sender as ListView;
    if (_list != this.list) 
       throw new Exception("The event sender does not match the list");

    //sweap columns, which are no longer contained by the list
    CleanUp();

    //get clicked column header
    ColumnHeader _column = this.list.Columns[e.Column];

    //activate sort by that header
    SortBy(_column, this.column ! =_column || 
                    this.list.Sorting!=SortOrder.Ascending);
}

That active column later is used by sorting logic to choose correct comparer and to compare cells.

//activates sort by column
public void SortBy(ColumnHeader _column, bool asc)
{
    //validate column
    if (this.list == null) throw new Exception("The list is null");
    if (_column == null) throw new Exception("The column is null");

    //leav old sort if column is not sortable
    if (this[_column] == null) return;

    //activate column
    this.column = _column;

    //activate sort
    this.list.Sorting = SortOrder.None;
    this.list.Sorting = asc ? SortOrder.Ascending : SortOrder.Descending;
}

Bellow is cell comparison through the Comparer implementation.

//cell comparison
int IComparer.Compare(object x, object y)
{
    //validate list
    if (this.list == null || this.list.Sorting == SortOrder.None 
      || this.column == null) return 0;

    //get cells
    ListViewItem ix = x as ListViewItem;
    ListViewItem iy = y as ListViewItem;
    if (ix.ListView != this.list || iy.ListView != this.list)
        throw new Exception("The event sender does not match the list");

    //compare - use column comparer
    return
        (this.list.Sorting==SortOrder.Ascending ? 1:-1) *
        this[this.column](ix.SubItems[this.column.Index].Text, 
                          iy.SubItems[this.column.Index].Text);
}

ListViewSorter already has standard comparers (as static methods) for strings, numbers, dates.

History

  • 23 May 2003 - updated download