ListView項目の並べ替え
IComparerインターフェイスを実装したクラスを用いるということは分かっていたので、「ListViewの項目を並び替える: .NET Tips: C#, VB.NET, Visual Studio」を参考にさせていただいた。
ついでに通常のWindowsフォームのリストビューのようにソート方向を示す三角印を付けたかったのだが、検索しても手頃なサンプルコードがなかったので自力でどうにかしてみることにした。
調べてみると.NET Framework 1.1にはそもそもColumnHeaderに画像を表示するための機能が実装されていないらしいので、「PRB:ビジュアルC#.NETの Windows フォーム ListView コントロールの ColumnHeader コントロールにイメージを割り当てることができません。」を応用してみることにした。
/// <summary> /// リストビューの列ヘッダがクリックされたとき /// </summary> private void listView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e) { // 並べ替え listViewItemSorter.Column = e.Column; listView1.Sort(); IntPtr hc; int i; // ヘッダコントロールのハンドルを取得 hc = SendMessage(listView1.Handle,LVM_GETHEADER,(UInt32)0,(UInt32)0); // ヘッダコントロールに imageList1 を追加 SendMessage(hc,HDM_SETIMAGELIST,(UInt32)0,(UInt32)imageList1.Handle); // 各列に画像を割り当てる // 列のイメージインデックスを設定するのに LVM_SETCOLUMN メッセージを使う LVCOLUMN col; col.mask = LVCF_FMT | LVCF_IMAGE; col.fmt = LVCFMT_IMAGE | LVCFMT_BITMAP_ON_RIGHT; // 0で初期化 col.pszText = (IntPtr)0; col.cchTextMax = 0; col.cx = 0; col.iSubItem = 0; col.iOrder = 0; // 画像割り当て for (i = 0; i < listView1.Columns.Count; i++) { col.iImage = -1; SendMessage(listView1.Handle,LVM_SETCOLUMN,(UInt32)i,ref col); } if(listViewItemSorter.Order == SortOrder.Ascending) { col.iImage = 0; } else { col.iImage = 1; } // LVM_SETCOLUMN メッセージを送る // 画像を割り当てる列は3番目のパラメータで定義されている SendMessage(listView1.Handle,LVM_SETCOLUMN,(UInt32)e.Column,ref col); }
imageList1の0番目に昇順用の三角形、1番目に降順用の三角形が割り当てられている。あと右側に表示するためにLVCOLUMN.fmtにLVCFMT_BITMAP_ON_RIGHT (4096)を加算した。クリックされた列以外の三角形を消すために一度すべての列に存在しないインデックスを指定している。これが呼び出される以上SortOrder.Noneにはならないはずなのでif〜elseだけで十分のはず。
ちょっと調べただけの付け焼き刃なのだけど、これで大丈夫かな?