すみません。ListViewコントロールについて再度教えてください。
ListViewのコントロールプロパティにてSortingプロパティをAscendingとして
セルに追加されたアイテムを昇順ソートするようにしていますが
セルにはString型の配列の中身をFor文でループさせてItem.Addメソッドで追加
しています。
配列の中身が
a[0]・・・7
a[1]・・・8
a[2]・・・9
a[3]・・・10
a[4]・・・11
とString型の数値が格納されているのですがこれをListViewへ追加するとList
Viewの表示順が
10
11
7
8
9
となってしまいます。これを簡単に昇順ソートするにはどのようにすればいい
でしょうか?
昇順というのが,int型において昇順ソートであると仮定します。
# String型の数値はありえないし,String型の昇順ソートとして結果は正しいので。
Sortingプロパティのヘルプにある通り,ListViewItemSorterを設定してやる必要があり
ます。
 http://msdn.microsoft.com/ja-jp/library/ 
system.windows.forms.listview.sorting.aspx
 http://msdn.microsoft.com/ja-jp/library/ 
system.windows.forms.listview.listviewitemsorter.aspx
YuOさん
回答ありがとうございました。
>Sortingプロパティのヘルプにある通り,ListViewItemSorterを設定し
>てやる必要があります。
MSDNにて調べたのですがListViewItemSorterを使用するには別クラスを
作成しなければならないのでしょうか?
出来る限り簡単にやりたかったのですが・・。
> MSDNにて調べたのですがListViewItemSorterを使用するには別クラスを
> 作成しなければならないのでしょうか?
そうです。
IComparerを継承したクラスを生成するか,
ListViewItemを継承し,IComparable or IComparable<ListViewItem>を継承したクラスを
生成してListViewItemSorterにはComparer.Default等を渡すか,です。
> 出来る限り簡単にやりたかったのですが・・。
難しいところはどこかにありますか?
nullの存在を無視すれば,IComparerの継承クラスなんて数行でしょうに……。
class Comparer : System.Collections.IComparer
{
    public static readonly Comparer Default = new Comparer(); // 
System.Collections.Comparerなどに倣ってDefaultを用意してみた。
    public int Compare (object x, object y)
    {
        ListViewItem x1 = (ListViewItem)x, y1 = (ListViewItem)y;
        int x2 = Int32.Parse(x1.Text), y2 = Int32.Parse(y1.Text);
        return x2.CompareTo(y2);
    }
}
昔作ったサンプルがあったので貼っときます。
using System.Collections;
private void listView1_ColumnClick(object sender, ColumnClickEventArgs e) {
  listView1.ListViewItemSorter = new ListViewItemComparer(e.Column, 
sortOrder);
  listView1.Sort();
  // 次回は逆順
  sortOrder *= -1;
  sortColumn = e.Column;
}
class ListViewItemComparer : IComparer {
  private int col;
  private int sortOrder;
  // コンストラクタ
  public ListViewItemComparer(int col, int sortOrder) {
    this.col=col;
    this.sortOrder = sortOrder;
  }
  // 比較メソッド
  public int Compare(object x, object y) {
    int ret = 0;
    switch (col) {
    case 0:	// 文字列でソート
      ret = String.Compare(((ListViewItem)x).SubItems[col].Text, 
          ((ListViewItem)y).SubItems[col].Text);
      break;
    case 1:	// 数値でソート
      ret = int.Parse(((ListViewItem)x).SubItems[col].Text) < 
         int.Parse(((ListViewItem)y).SubItems[col].Text) ? -1 : 1;
      break;
    }
    return ret * sortOrder;
  }
}
VC++なら StrCmpLogicalW() という便利なAPIがあるんですけどねぇ
YuOさん、FUKUさん
ご返事遅くなりすみません。アドバイスありがとうございました。上記の通り
IComparerの継承クラスを作成したところ上手くソートすることが出来ました。
ただ上記のサンプルコードのようにListViewのColumnClickイベントハンドラで
ソート出来るようになっているのでこれをColumnClickではなくフォーム上の
ボタン押下でListViewへアイテムをAddする時にAddされたものをソートしたいの
です。この場合はボタン押下イベントでListViewItemSorterを設定すると思いま
すが
ListView1.ListViewItemSorter = New ListViewItemComparer(e.Column)
上記のe.Columnではこの場合何を渡せばいいのでしょうか?カラムは3列あって
1列目でソートをかけたいと思っています。
IComparerの継承クラスは以下です↓
public class ListViewItemComparer : IComparer
{
    private int _column;
    /// <summary>
    /// ListViewItemComparerクラスのコンストラクタ
    /// </summary>
    /// <param name=col>並び替える列番号</param>
    public ListViewItemComparer(int col)
    {
        _column = col;
    }
    //xがyより小さいときはマイナスの数、大きいときはプラスの数、
    //同じときは0を返す
    public int Compare(object x, object y)
    {
        //ListViewItemの取得
        ListViewItem itemx = (ListViewItem) x;
        ListViewItem itemy = (ListViewItem) y;
        //xとyを文字列として比較する
        return string.Compare(itemx.SubItems[_column].Text,
            itemy.SubItems[_column].Text);
    }
}
>>上記のe.Columnではこの場合何を渡せばいいのでしょうか?
>>カラムは3列あって1列目でソートをかけたいと思っています。
パラメータの引数がそのまま列番号なのでint colには1を渡せば
いいんですかね。手元に環境が無いので推測になってしまいます
が・・・。
添字は0から数えるので,先頭の列でソートしたいのであれば,0を指定する必要がありま
す。
YuOさん
こんばんは。さっそくの回答ありがとうございます。
>>添字は0から数えるので,先頭の列でソートしたいのであれば,0を指定する
>>必要があります。
そうでした、0始まりでしたね(^^);
連休明けに実機にて確認してまた報告させて頂きます。いろいろとアドバイスありがと
うございました。
皆様のアドバイスのお陰で実装して問題なくソートできることを
確認しました。
そこで再度お聞きしたいことがありますが
>>ListViewのColumnClickイベントハンドラで
>>ソート出来るようになっているのでこれをColumnClickではなくフォーム上の
>>ボタン押下でListViewへアイテムをAddする時にAddされたものをソートしたいの
>>です。この場合はボタン押下イベントでListViewItemSorterを設定すると思いま
>>すが
この処理は別にボタン押下イベントで記述しなくてもいいのでしょうか?最初に呼ばれ
るコンストラクタで
ListView1.ListViewItemSorter = New ListViewItemComparer();
を定義しても上手くいきました。どちらがコードの記述として正しいのでしょうか?
すいません、勘違いでした。先程の質問は解決済みです。
すみません、解決チェック忘れていました・・・。
