ListViewのListItemの順番を入れかえたいのですが、
スマートな方法を探しています。
どうすればいいのでしょうか?
ちなみに手順としてはPopUpMenuで[上へ]ボタンを押して選択されている行を上に移動するという感じです。
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;
Halbowさん、ありがとうございます。
やはりこのやり方くらいしかないのですね。
解決ということでチェックつけました。
継承コンポーネントを作って、そんなメソッドをつくってしまえば、
それが十分"スマートな"方法になりうると思います。
わたしはそれが面倒なので、オーナードローを施したリストボックスで代用してます。
ちなみに、ローマ数字の3は機種依存文字です。
ちゃんと表示できないことがあるので、あんまりインターネット上では使わないでくださいね。
ちょっと大げさですが、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;
ツイート | ![]() |