Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#

An extendable ListViewSorter

Rate me:
Please Sign up or sign in to vote.
4.65/5 (13 votes)
12 Oct 2006CPOL5 min read 63K   1.1K   52  
This article describes how to sort a ListView ascending/descending with two lines of code, and how to extend its sorting capabilities.
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using Yaowi.Common.Collections;

namespace Yaowi.Common.Windows.Controls
{
  /// <summary>
  /// Sorts a ListView by arbitray columns.
  /// </summary>
  public class ListViewSorter : IDisposable
  {
    #region Members

    private Dictionary<string, ISortComparer> comparercollection = new Dictionary<string, ISortComparer>();
    private int lastsortcolumn = -1;
    private Yaowi.Common.Collections.SortOrder sortorder = Yaowi.Common.Collections.SortOrder.Descending;
    private ListView listview = null;
    private string imagekeyup = "up";  // Default, but mostly not correct
    private string imagekeydown = "down"; // Default, but mostly not correct

    #endregion Members

    #region Constructors

    /// <summary>
    /// Constructor.
    /// </summary>
    public ListViewSorter()
    {
    }

    /// <summary>
    /// Constructor.
    /// </summary>
    /// <param name="listView"></param>
    public ListViewSorter(ListView listView)
    {
      this.ListView = listView;
    }

    #endregion Constructors

    #region Properties

    /// <summary>
    /// Gets or sets the ListView.
    /// </summary>
    public ListView ListView
    {
      get { return listview; }
      set
      {
        // Unregister previous EventHandler
        if (this.listview != null)
          this.listview.ColumnClick -= this.listview_ColumnClick;

        listview = value;

        // Register EventHandler
        if(listview!=null)
          this.listview.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listview_ColumnClick);
      }
    }

    /// <summary>
    /// Gets or sets the Collection of ISortComparers.
    /// </summary>
    public Dictionary<string, ISortComparer> ColumnComparerCollection
    {
      get { return comparercollection; }
      set { comparercollection = value; }
    }

    /// <summary>
    /// Key of the arrow-up image in the ListViews SmallImageList.
    /// </summary>
    public string ImageKeyUp
    {
      get { return imagekeyup; }
      set { imagekeyup = value; }
    }

    /// <summary>
    /// Key of the arrow-down image in the ListViews SmallImageList.
    /// </summary>
    public string ImageKeyDown
    {
      get { return imagekeydown; }
      set { imagekeydown = value; }
    }

    #endregion Properties

    #region Methods

    /// <summary>
    /// Handles the ListViews ColumnClick event.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void listview_ColumnClick(object sender, ColumnClickEventArgs e)
    {
      Sort(e.Column);
    }

    /// <summary>
    /// Sorts the ListView by the specified column.
    /// </summary>
    /// <param name="column"></param>
    protected void Sort(int column)
    {
      // Toggle ASC and DESC
      if (column == lastsortcolumn)
      {
        if (sortorder == Yaowi.Common.Collections.SortOrder.Ascending)
          sortorder = Yaowi.Common.Collections.SortOrder.Descending;
        else
          sortorder = Yaowi.Common.Collections.SortOrder.Ascending;
      }
      else
      {
        sortorder = Yaowi.Common.Collections.SortOrder.Ascending;
      }

      lastsortcolumn = column;

      // Get the columns comparer (if the column ist registered use the StringComparer by default)
      ISortComparer c = null;
      if (comparercollection.ContainsKey(this.ListView.Columns[column].Text))
        c = comparercollection[this.ListView.Columns[column].Text];
      else
        c = new Yaowi.Common.Collections.StringComparer();

      // Initialize the ListViewItemComparer
      ListViewItemComparer lvc = new ListViewItemComparer(column, c);
      lvc.SortOrder = sortorder;
      this.ListView.ListViewItemSorter = lvc;

      // Sort!
      this.ListView.Sort();

      // Set ColumnHeaders image
      SetImage(column, sortorder);
    }

    /// <summary>
    /// Sets the image of the sorted ColumnHeader.
    /// </summary>
    /// <param name="column"></param>
    /// <param name="sortorder"></param>
    protected void SetImage(int column, Yaowi.Common.Collections.SortOrder sortorder)
    {
      // Nothing to do
      if (this.listview.SmallImageList == null)
        return;

      string key = String.Empty;

      foreach (ColumnHeader ch in this.ListView.Columns)
      {
        ch.ImageKey = null;
      }

      if (sortorder == Yaowi.Common.Collections.SortOrder.Ascending)
        key = imagekeyup;
      else
        key = imagekeydown;

      if (key!=null && this.listview.SmallImageList.Images.ContainsKey(key))
      {
        this.ListView.Columns[column].ImageKey = key;
      }
    }

    /// <summary>
    /// Clean up.
    /// </summary>
    public void Dispose()
    {
      // Make sure there is no registered EventHandler left
      if (this.listview != null)
        this.listview.ColumnClick -= this.listview_ColumnClick;

      comparercollection.Clear();
    }

    #endregion Methods
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany Germany
I am working for a small software company in Hamburg, Germany, and my day-to-day distress is Java development.

Comments and Discussions