C++BuilderでTListViewをStyle:vsReportで使用している場合、Group名順に並び替えるには、GoupItemのIndexプロパティを変更するだけでいい。(GroupViewプロパティはTrue)
以下のコードでは、std::mapにGroup名とTListGroup(のポインタ)を格納して、自動的に名前順に並び替えている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <map> void __fastcall TForm1::Button1Click(TObject *Sender) { std::map<String,TListGroup*> HeaderGroupMap; for( int i = 0; i < ListView->Groups->Count; ++i ) { TListGroup* Group = ListView->Groups->Items[i]; HeaderGroupMap[Group->Header] = Group; } int index = 0; for( auto it = HeaderGroupMap.begin(); it != HeaderGroupMap.end(); ++it ) { it->second->Index = index++; } } |
なお、このサンプルでは、名前のないGroupが先頭に来てしまう。名前のないGroupを最後にするには、Indexを明示的に付けなけれぱOK。自動的に最後になる。(正確に言うと自動的にカウントアップされたIndexが割り振られる)
1 2 3 4 5 |
for( auto it = HeaderGroupMap.begin(); it != HeaderGroupMap.end(); ++it ) { if( !it->second->Header.IsEmpty() ) it->second->Index = index++; } |
以下、蛇足。
Indexプロパティって何?
ListViewにGroupを動的に追加する場合、GroupIDは自分で設定するけど、Indexは特に指定しない。
Indexプロパティは、GroupがAddされるたびに自動的に連番で振られる(らしい)。
ちなみに以下のようにループを回すと、GroupID順でなくIndex順にアクセスされる。(GroupID順だと思い込んでバグったことがある)
1 2 3 4 |
for( int i = 0; i < ListView->Groups->Count; ++i ) { TListGroup* Group = ListView->Groups->Items[i]; } |
なおIndexを指定する場合、ダブりを気にする必要はない。
つまり
グループ0 | Index = 0 |
グループ1 | Index = 1 |
グループ2 | Index = 2 |
この「グループ2」のIndexを0に変更すると、以下のように全グルーブのIndexが割り振り直される。
グループ0 | Index = 1 |
グループ1 | Index = 2 |
グループ2 | Index = 0 |
なので、Groupの最後を先頭に持ってくるのは以下のコードですむ。
1 2 3 4 |
if( ListView->Groups->Count > 1 ) { ListView->Groups->Items[ListView->Groups->Count-1]->Index = 0; } |
(なお”Group->Count-1″を超えるIndexを指定すると例外が投げられる。)
ここらへん、TListGroupsの継承元のTCollectionクラスあたりの仕様を把握していると直感的に分かるのかもしれないけど、ちょっと苦労した。
Windows7(64bit)/C++Builder Berlin(Update1)で確認