TListViewのItemをソートする3方法[Vcl]

TListViewのソート方法については、ヘルプのコード例を見てもいまいち分からなかったので整理してみる。(Style:vsReportの場合)。
まだ正確に把握しきってない可能性はあるが…。

まず、ListViewでは以下の3方法のSortが可能。
 stText…いわゆる文字列ソート。ListItemのCaption順にソートする
 stData…ListItemに格納されたDataを比較する
 stBoth…上記両方でソート(たぶん)

1.stSort

これは単純。TListViewのSotrTypeプロパティにstTextを指定するだけ。コードを書く必要はない。

2.stData

こっちは、事前にListItemのDataプロパティに何かの値をセットしておく必要がある。
たとえばクラスのポインタとか。

実例として、各ItemのDataが、intメンバを持つクラスのポインタを保有している場合。(エラー処理は省略)

Compoare値が0より大きいか小さいか、でソート順が決まる。

3.stBoth

ここがちょっと分かりにくいパターン。
基本的に、まずデータを比較し、同じ場合はTextを比較するという手順を踏む(たぶん)
コード例。

4.実行時にTSortTypeを変えたい場合

アプリケーションのオプション設定等でSortTypeを変更したい場合は、ちょっと面倒。
ここで気になるのがListViewのOnCompareイベントの引数
 int Data
とは何だろうってこと。
ヘルプをざっと見た限りだと、こういう事らしい。
 Data == 0 なら、stTextかstNone
 Data != 0 なら、stDataかstBoth

ということで、仮に実行時にSortTypeを変更し、反映したい場合は、以下のようなコードになるはず。

うーん、このコードだと、そもそも引数のDataを利用する必要がないような…。
もっとスマートな方法がある気がする。

TListViewをGroup名順に並び替える[Vcl]

C++BuilderでTListViewをStyle:vsReportで使用している場合、Group名順に並び替えるには、GoupItemのIndexプロパティを変更するだけでいい。(GroupViewプロパティはTrue)

以下のコードでは、std::mapにGroup名とTListGroup(のポインタ)を格納して、自動的に名前順に並び替えている。

なお、このサンプルでは、名前のないGroupが先頭に来てしまう。名前のないGroupを最後にするには、Indexを明示的に付けなけれぱOK。自動的に最後になる。(正確に言うと自動的にカウントアップされたIndexが割り振られる)

以下、蛇足。

Indexプロパティって何?

ListViewにGroupを動的に追加する場合、GroupIDは自分で設定するけど、Indexは特に指定しない。
Indexプロパティは、GroupがAddされるたびに自動的に連番で振られる(らしい)。
ちなみに以下のようにループを回すと、GroupID順でなくIndex順にアクセスされる。(GroupID順だと思い込んでバグったことがある)

なおIndexを指定する場合、ダブりを気にする必要はない。

つまり

グループ0Index = 0
グループ1Index = 1
グループ2Index = 2

この「グループ2」のIndexを0に変更すると、以下のように全グルーブのIndexが割り振り直される。
グループ0Index = 1
グループ1Index = 2
グループ2Index = 0

なので、Groupの最後を先頭に持ってくるのは以下のコードですむ。

(なお”Group->Count-1″を超えるIndexを指定すると例外が投げられる。)

ここらへん、TListGroupsの継承元のTCollectionクラスあたりの仕様を把握していると直感的に分かるのかもしれないけど、ちょっと苦労した。

Windows7(64bit)/C++Builder Berlin(Update1)で確認