1

私は VirtualTreeView コンポーネントについて多くの賞賛を聞いており、私たちが行っている書き直しでそれを使用することを検討しました。現在、StringGrid を使用しています。

単一の列の並べ替えはうまく機能しますが、複数の列を並べ替える方法が見つかりません。列1をクリック>並べ替え、Ctrlキーを押しながら列2をクリック>列1の後に列2を並べ替えるなどの方法はありますか?

具体的には、PO Number、Line Item、Release の少なくとも 3 つの列を並べ替えたいと考えています。

よろしくお願いします。

これがコードです(少し簡略化されています)(上記で参照した同じプロジェクトからではなく)理論をテストしています:

注:更新後、現在のコードを表示するためにコードも編集しました。以下に、並べ替えの結果を投稿しました。

type
  PBatchDetails = ^TBatchDetails;
  TBatchDetails = record
    TheBatchKey
    OperationKey,
    PO,
    Line,
    Release,
    Temp,
    Notes : String;
    TransDate : TDateTime;
end;

....
Sorting_Columns: array of TColumnIndex;
....
procedure TForm1.TreeHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
var
  I: Integer;
begin
  if not CtrlDown then //function I have to test Ctrl state.
  begin
    setlength(Sorting_Columns,0);
  end;
  SetLength(Sorting_Columns,length(Sorting_Columns)+1);
  Sorting_Columns[Length(Sorting_Columns)-1] := HitInfo.Column;
  tree.SortTree(HitInfo.Column,Sender.SortDirection,True);
  if Sender.SortDirection=sdAscending then
    Sender.SortDirection:=sdDescending
  else
    Sender.SortDirection:=sdAscending
end;


procedure TForm1.TreeCompareNodes(Sender: TBaseVirtualTree; Node1,
  Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
  BatchRec1 : PBatchDetails;
  BatchRec2: PBatchDetails;
  I: Integer;
begin
  if length(Sorting_Columns) > 0 then
  begin
    BatchRec1 := Tree.GetNodeData(Node1);
    BatchRec2 := Tree.GetNodeData(Node2);
    if (not Assigned(BatchRec1)) or (not Assigned(BatchRec2)) then
      Result:=0
    else
    begin
      for I := High(Sorting_Columns) downto 0 do
      begin
        case Sorting_Columns[i] of
          0,1: Result := Result + CompareDate(BatchRec1.TransDate,BatchRec2.TransDate); // col 0 is Date and col 1 is Time.
          2: Result := Result + CompareText(BatchRec1.OperationKey,BatchRec2.OperationKey);
          3: Result := Result + CompareText(BatchRec1.PO,BatchRec2.PO);
          4: Result := Result + CompareText(BatchRec1.Line,BatchRec2.Line);
          5: Result := Result + CompareText(BatchRec1.Release,BatchRec2.Release);
          6: Result := Result + CompareText(BatchRec1.Temp, BatchRec2.Temp);
          7: Result := Result + CompareText(BatchRec1.Notes,BatchRec2.Notes);
        end; //end case;
        if Result <> 0 then
          Break;
      end;
    end;
  end;
end;

これにより、次の結果が生成されました (ここでは、並べ替えようとしている 3 つの列のみを表示しています)。

最初にロードされたとき:
注文明細リリース
153 7 2
153 7 1
153 1 1
153 1 2
153 4 1
153 6 2
153 6 1
120 3 2
120 3 1
153 2 1
153 4 2
120 2 1
153 4 1
120 1 1
153 3 1
153 2 1
111 2 1
111 1 5
111 1 1
111 4 2
111 3 1
111 4 1
111 1 3
111 1 2
111 1 4

最初のクリック後
注文明細のリリース
111 2 1
111 1 5
111 1 1
111 4 2
111 3 1
111 4 1
111 1 3
111 1 2
111 1 4
120 3 2
120 3 1
120 2 1
120 1 1
153 7 2
153 7 1
153 1 1
153 1 2
153 4 1
153 6 2
153 6 1
153 2 1
153 4 2
153 4 1
153 3 1
153 2 1

2 回目のクリック後
注文明細のリリース
153 7 2
153 7 1
153 6 2
153 6 1
153 4 1
153 4 2
153 4 1
111 4 2
111 4 1
153 3 1
120 3 2
120 3 1
111 3 1
153 2 1
153 2 1
120 2 1
111 2 1
153 1 1
153 1 2
120 1 1
111 1 5
111 1 1
111 1 3
111 1 2
111 1 4

3 回目のクリック後
注文明細のリリース
111 1 1
120 1 1
153 1 1
111 2 1
120 2 1
153 2 1
153 2 1
111 3 1
120 3 1
153 3 1
111 4 1
153 4 1
153 4 1
153 6 1
153 7 1
111 1 2
153 1 2
120 3 2
111 4 2
153 4 2
153 6 2
153 7 2
111 1 3
111 1 4
111 1 5

御時間ありがとうございます!

4

2 に答える 2

2

一般的に、すべての自動ソート オプションを無効にします。次に、OnCompareNodes と OnHeaderClick イベントを実装する必要があります。

ここにコードが機能することを願っています(簡単なテストを行いました:)

目的は、並べ替え列を変数 (Sorting_Columns) に格納することです。この変数は、OnHeaderClick イベントでフィードできます。
SortTree 関数の呼び出し後にトリガーされる OnCompareNodes イベントで、最後に追加された列から最初に追加された列まで変数を反復し、最初のゼロ以外の比較結果を Result パラメーターに渡します。ここで人間的に-「選択」された列を逆方向に調べて、それらが同じかどうかを確認し、同じ場合は以前に選択したものに移動し、そうでない場合はループを中断して結果を渡す必要があります。1 つのイベント ヒットで 2 つのノード (行) を比較していることに注意してください。列の並べ替えの反復とその後の比較の理由は何ですか。

type
  PRecord = ^TRecord;
  TRecord = record
    ID: integer;
    Text_1: string;
    Text_2: string;
    Text_3: string;
    Date: TDateTime;
  end;

...

var Sorting_Columns: array of TColumnIndex;

...

procedure TForm1.VirtualStringTree1CompareNodes(Sender: TBaseVirtualTree;
  Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var Actual_Index: integer;
    Data_1: PRecord;
    Data_2: PRecord;

begin
  if Length(Sorting_Columns) > 0 then
    begin
      Data_1 := VirtualStringTree1.GetNodeData(Node1);
      Data_2 := VirtualStringTree1.GetNodeData(Node2);

      if Assigned(Data_1) and Assigned(Data_2) then
        for Actual_Index := High(Sorting_Columns) downto 0 do
          case Sorting_Columns[Actual_Index] of
            0: Result := Result + Data_1^.ID - Data_2^.ID;
            1: Result := Result + CompareStr(Data_1^.Text_1, Data_2^.Text_1);
            2: Result := Result + CompareStr(Data_1^.Text_2, Data_2^.Text_2);
            3: Result := Result + CompareStr(Data_1^.Text_3, Data_2^.Text_3);
            4: Result := Result + CompareDateTime(Data_1^.Date, Data_2^.Date);
          end;

      if Result <> 0 then
        Break;
    end;
end;
于 2010-12-15T15:50:58.123 に答える