ListViewの項目を自動でソートする

 ListViewは、その項目であるListViewItemを自動的に並び替えるためのメンバーを持っています。ListViewItem.ListViewItemSorterプロパティがそれですが、このプロパティのクラスはSystem.Collections.IComparerです。したがって、IComparerを実装クラスを用意して、その実体をListViewItemSorterプロパティに代入すればよいことになります。

 しかし、比較が必要な場面が出てくるたびに1つずつクラスを作っていたのでは面倒なので、比較用メソッドを格納するだけのクラスを作ってしまいます。

// 比較用メソッドを格納しておくクラス
class DelegateComparison : System.Collections.IComparer
{
  // 比較用メソッドの型を表すデリゲート
  public delegate int CompareFunc(object a,object b);

  // 比較用メソッドを格納するフィールド
  CompareFunc func;

  // DelegateComparisonの構築子
  public DelegateComparison(CompareFunc func)
  {
    // 指定されたメソッドを格納するだけ。
    this.func=func;
  }

  // IComparerのCompareメソッドを実装
  public int Compare(object a,object b)
  {
    // 比較用メソッドを呼び出すだけ
    return this.func(a,b);
  }
}

 このクラスのCompareメソッドを呼び出すと、あらかじめ構築子の引数として渡しておいたメソッドを実行します。デリゲートになじみのない方は、「func」はメソッドを代入しておく変数だと思ってください。どんなメソッドでも代入できるわけではなく、返却値の型と、全ての引数の型が一致していなければなりません。

 ここまで実装できれば、あとはDelegateComparisonクラスのオブジェクトを作り、ListViewItem.ListViewItemSorterプロパティに代入するだけです。下記のソースでは、indexフィールドとdescendingフィールドで、ソートに使用する列とソート順(昇順、逆順)を指定しています。

public partial class Form1 : Form
{
  // 実際に比較するメソッド
  int ItemCompare(object a,object b)
  {
    // 単純に型変換
    ListViewItem itemA=(ListViewItem)a;
    ListViewItem itemB=(ListViewItem)b;
    
    // 比較したい列を取得
    string textA=itemA.SubItems[column].Text;
    string textB=itemB.SubItems[column].Text;

    // 比較
    int result=textA.CompareTo(textB);
    
    // 逆順ソートなら-1倍して返す。
    if(descending) return -result;
    else return result;
  }

  // ソートに使用する列
  int column;

  // trueなら逆順ソート
  bool descending;

  // フォームデザイナが生成した構築子
  public Form1()
  {
    InitializeComponent();

    this.column=1;
    this.descending=true;

    // 比較用メソッドを登録する。
    listView.ListViewItemSorter
      =new DelegateComparison(this.ItemCompare);
  }

}

// 比較用メソッドを格納しておくクラス
class DelegateComparison : System.Collections.IComparer
{
  // 比較用メソッドの型を表すデリゲート
  public delegate int CompareFunc(object a,object b);

  // 比較用メソッドを格納するフィールド
  CompareFunc func;

  // DelegateComparisonの構築子
  public DelegateComparison(CompareFunc func)
  {
    // 指定されたメソッドを格納するだけ。
    this.func=func;
  }

  // IComparerのCompareメソッドを実装
  public int Compare(object a,object b)
  {
    // 比較用メソッドを呼び出すだけ
    return this.func(a,b);
  }
}