ListViewのListItemの順番を入れかえるには?

解決


LupinⅢ  2003-06-05 22:51:36  No: 3698

ListViewのListItemの順番を入れかえたいのですが、
スマートな方法を探しています。
どうすればいいのでしょうか?

ちなみに手順としてはPopUpMenuで[上へ]ボタンを押して選択されている行を上に移動するという感じです。


Halbow  2003-06-06 00:05:47  No: 3699

Halbow です。

> ListViewのListItemの順番を入れかえたいのですが、
> スマートな方法を探しています。

スマートじゃない方法ではうまくいっているのですね。

わたしが思いつくのは、Insert - Assign - Delete のサイクルです。
スマートじゃないですが、以下にコードを載せておきます。

type
  TForm1 = class(TForm)
    ListView1: TListView;
    btnUpper: TButton;
    btnLower: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnUpperClick(Sender: TObject);
    procedure btnLowerClick(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  ListView1.ViewStyle := vsReport;
  ListView1.RowSelect := true;
  for i := 0 to 2 do
    with ListView1.Columns.Add do begin
      width := 100;
      Caption := Format('Column %d',[i]);
    end;
  for i := 0 to 10 do
    with ListView1.Items.Add do begin
      Caption := Format('Caption %.2d',[i]);
      SubItems.Add(Format('SubItem1 %.2d',[i]));
      SubItems.Add(Format('SubItem2 %.2d',[i]));
    end;
  ListView1.Selected := ListView1.Items[5];;
end;

procedure TForm1.btnUpperClick(Sender: TObject);
var
  SelIndex:integer;
  LI:TListItem;
begin
  SelIndex := ListView1.Selected.Index;
  if SelIndex > 0 then begin
    LI := ListView1.Items.Insert(SelIndex-1);
    LI.Assign(ListView1.Items[SelIndex+1]);
    ListView1.Items.Delete(SelIndex+1);
    ListView1.Selected := ListView1.Items[SelIndex-1];
    ListView1.ItemFocused := ListView1.Selected;
  end;
  ListView1.SetFocus;
end;

procedure TForm1.btnLowerClick(Sender: TObject);
var
  SelIndex:integer;
  LI:TListItem;
begin
  SelIndex := ListView1.Selected.Index;
  if SelIndex < ListView1.Items.Count-1 then begin
    LI := ListView1.Items.Insert(SelIndex+2);
    LI.Assign(ListView1.Items[SelIndex]);
    ListView1.Items.Delete(SelIndex);
    ListView1.Selected := ListView1.Items[SelIndex+1];
    ListView1.ItemFocused := ListView1.Selected;
  end;
  ListView1.SetFocus;
end;


LupinⅢ  2003-06-06 02:31:27  No: 3700

Halbowさん、ありがとうございます。
やはりこのやり方くらいしかないのですね。

解決ということでチェックつけました。


たかみちえ  URL  2003-06-06 05:33:25  No: 3701

継承コンポーネントを作って、そんなメソッドをつくってしまえば、
それが十分"スマートな"方法になりうると思います。

  わたしはそれが面倒なので、オーナードローを施したリストボックスで代用してます。

  ちなみに、ローマ数字の3は機種依存文字です。
ちゃんと表示できないことがあるので、あんまりインターネット上では使わないでくださいね。


にしの  2003-06-06 08:25:30  No: 3702

ちょっと大げさですが、CustomSortを使うのはどうでしょう。
.Dataプロパティがあいていれば、次のようになります。
あいていなくても、Dataプロパティに持たせる値をclassのオブジェクトなり、構造体なりにして、順序を保持できればOKです。

  for i := 0 to 9 do
  begin
    Item := ListView1.Items.Add;

    Item.Caption := 'TEST-' + IntToStr(i);
    Item.Data := Pointer(i);
  end;
*上のように、Item.Dataに順序を入れてあるとする。順序は重複しないものとする

function SortProc(Item1, Item2: TListItem; ParamSort: integer): integer; stdcall;
var
  idx1, idx2: Integer;
begin
  idx1 := Integer(Item1.Data);
  idx2 := Integer(Item2.Data);

  if idx1=idx2 then Result :=  0;
  if idx1<idx2 then Result := -1;
  if idx1>idx2 then Result :=  1;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  idx1, idx2: Integer;
  tmp: Pointer;
begin
  idx1 := StrToIntDef(Edit1.Text, -1);//交換したいItemその1
  idx2 := StrToIntDef(Edit2.Text, -1);//交換したいItemその2

  //位置交換(順序を入れ替えるだけ)
  tmp := ListView1.Items[idx1].Data;
  ListView1.Items[idx1].Data := ListView1.Items[idx2].Data;
  ListView1.Items[idx2].Data := tmp;

  //ソート
  ListView1.CustomSort(@SortProc, 0);
end;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加