TcxGridのソート
2010/3/8 内容を修正しました。
TcxGridのソートについて。CustomDataSourceを使ったUnbound modeではなく、DataSetを使ったProvider modeでの話です。
Viewについては、DBTableView又はDBBandedTableViewを想定してます。
ViewのDataController.DataModeController.GridModeの値によって処理が変わってきます。
GridModeがFalseの場合は、ソートやフィルタなんかの処理はGrid側で面倒見てくれます。
ただ、全レコードをメモリに読み込んで処理するので、レコード数が少ない場合はこれで良いんですがレコード数が多くなってくるとパフォーマンスに問題が出てきます。(どの位まで大丈夫なのかはあんまり調べてないし、環境にもよると思うのでなんとも言えません。)
GridModeをTrueに設定すると決まったレコード数のみをメモリにロードするようになります。読み込むレコード数は、DataController.DataModeController.GridModeBufferCountで設定します。初期値の0を指定してあると表示されるレコード数から自動的に決定してくれるようです。
この時は、ソートやフィルタの処理は自分でやる必要が出てきます。
ソートの設定は、ViewのOptionsCustomize.ColumnSortingで設定した場合は、列全部がソート可能になります。
列に対して個別に設定する場合は、それぞれの列のOptions.Sortingで設定します。
ソートの許可された列のヘッダをクリックすると、その列に対するソートの設定をします。
列ヘッダをクリックするときにShiftを押しながらクリックすると現在のソートに追加して複数列のソートを設定する事が出来ます。
// カラムのソート順データを指定した順番に並び替える比較関数 function SortOrdersSort(List: TStringList; Index1, Index2: Integer): Integer; begin if Integer(List.Objects[Index1]) = Integer(List.Objects[Index2]) then Result := 0 else if Integer(List.Objects[Index1]) < Integer(List.Objects[Index2]) then Result := -1 else Result := 1; end;
上のコードはStringListのObjectsにInt値をキャストで無理矢理設定して、その値を使ってStringListをソートする処理です。下記のコードで、列をソートするときの設定された順番通りにORDER BYを組み立てるために利用します。
そして下記が、クリックで設定されたソート順に基づいてクエリのORDER BYの中身を組み立てる処理です。
// ORDER BYの中身を組み立てる。 function GetOrder: String; const CSORDERTYPE: Array[TcxDataSortOrder] of String=('', ' ASC',' DESC'); var Idx: Integer; Orders: TStringList; begin Result := ''; // StringListを利用して複数列にソート設定された場合の順番設定をします。 Orders := TStringList.Create; for Idx := 0 to cxView.ColumnCount - 1 do begin // まずは、全列に対してSortOrderがsoNone以外の列をStringListに追加します。 // この時、StringListに追加する文字列をデータベースのフィールド名だけで無く、SortOrderの設定に従って // フィールド名の後ろに昇順/降順を示す ASC/DESC を追加しておきます // また、列のSortIndexにソート設定された順番が入ってるのでこれをStringList.Objectsに入れておきます。 if cxView.Columns[Idx].SortOrder <> soNone then begin Orders.AddObject(cxView.Columns[Idx].DataBinding.FieldName + CSORDERTYPE[cxView.Columns[Idx].SortOrder], TObject(cxView.Columns[Idx].SortIndex)); end; end; if Orders.Count > 0 then begin // 指定された順番でソート条件を構築する Orders.CustomSort(SortOrdersSort); // ソートされたデータを順番に ','で区切ってつなげて文字列を返します。 Result := ' ORDER BY ' + Orders.Strings[0]; for Idx := 1 to Orders.Count - 1 do Result := Result + ',' + Orders.Strings[Idx]; end; FreeAndNil(Orders); end;