1

基本的には、ListView に StringList を設定したいのですが、ListItem を選択して Up または Down を押すと、アイテムが上下に移動します (両方のリストで)。

ListView の onKeyDown を使用して MoverFAT を呼び出しています

procedure TF_Aplicador.ListViewKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ListView.Selected <> nil then
    if Key = VK_UP then
      MoverFAT(ListView.Selected.Index, -1)
    else if Key = VK_DOWN then
      MoverFAT(ListView.Selected.Index, 1)
    else if Key = VK_DELETE then
      DeletarFAT(ListView.Selected.Index);
end; 

そして問題は、下に移動すると常に最初のアイテムが選択され(アイテムを交換した後)、上に移動すると問題なく動作することです。FATs は私の StringList であり、Atualizar() は ListView に StringList の内容を表示させるだけです。

procedure TF_Aplicador.MoverFAT(I, J: Integer);
begin
  if ((I + J) > -1) and ((I + J) < (FATs.Count)) then
  begin
    FATs.Exchange(I, I+J);
    Atualizar;
    ListView.Selected := ListView.Items[I+J];
  end;
end;
4

2 に答える 2

3

次のAtualizer実装で問題を再現しました。

  ListView.Clear;
  for I := 0 to FATs.Count - 1 do
    ListView.AddItem(FATs[I], nil);

(あなたが私たちにもそれを与えてくれたら、きっとずっと簡単だったでしょう。)

問題は、ListView 自体がキーを処理しようとすることですが、(おそらく)Atualizerルーチン内のすべての項目を削除したため、方法がわからないことです。

割り当てて、キーストロークをもう処理しないように ListView に指示することで解決します0

procedure TF_Aplicador.ListViewKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ListView.Selected <> nil then
  begin
    case Key of
      VK_UP: MoverFAT(ListView.ItemIndex, -1);
      VK_DOWN: MoverFAT(ListView.ItemIndex, 1);
      VK_DELETE: DeletarFAT(ListView.ItemIndex);
    end;
    if Key in [VK_UP, VK_DOWN, VK_DELETE] then
      Key := 0;
  end;
end; 

補足として、StringList と ListView を同期するためのより良い方法があります。Bummi のコメントから仮想アプローチを利用できます。または、ListView の項目も交換できます。この場合、キーを抑制する必要はもうありません。

procedure TForm1.ListViewKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ListView.Selected <> nil then
    case Key of
      VK_UP: MoverFAT(ListView.ItemIndex, -1);
      VK_DOWN: MoverFAT(ListView.ItemIndex, 1);
      VK_DELETE: DeletarFAT(ListView.ItemIndex);
    end;
end;

procedure ExchangeListItems(Items: TListItems; Index1, Index2: Integer);
var
  Item: TListItem;
begin
  Item := TListItem.Create(Items);
  try
    Item.Assign(Items[Index1]);
    Items[Index1].Assign(Items[Index2]);
    Items[Index2].Assign(Item);
  finally
    Item.Free;
  end;
end;

procedure TForm1.MoverFAT(I, J: Integer);
begin
  if ((I + J) > -1) and ((I + J) < (FATs.Count)) then
  begin
    FATs.Exchange(I, I + J);
    ExchangeListItems(ListView.Items, I, I + J);
  end;
end;
于 2013-04-22T18:23:53.340 に答える
2

NGLN がすでに問題を指摘している限り、別のアプローチをお勧めします。
リストビューにデータを保存しないでください。データの表示にのみ使用してください。デモンストレーションには、手を加えていない Liestview と Listbox のみが必要です。

unit Unit6;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls;

type
  TForm6 = class(TForm)
    ListView: TListView;
    ListBox1: TListBox;  // just for visualization should be an Stringlist
    procedure ListViewKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure ListViewData(Sender: TObject; Item: TListItem);
  private
    procedure MoverFAT(I, J: Integer);
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form6: TForm6;

implementation

var
  FATs: TStrings;
{$R *.dfm}

procedure TForm6.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to 9 do
    ListBox1.Items.Add(StringOfChar(IntToStr(I)[1], 10));
  ListView.Columns.Add.Caption := 'Test';
  ListView.ViewStyle := vsList;
  ListView.OwnerData := true;
  ListView.OnData := ListViewData;
  Listview.OnKeyDown := ListViewKeyDown;
  FATs := ListBox1.Items;
  ListView.Items.Count := FATs.Count;
end;

procedure TForm6.ListViewData(Sender: TObject; Item: TListItem);
begin
  Item.Caption := FATs[Item.Index];
end;

procedure TForm6.ListViewKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ListView.Selected <> nil then
    if Key = VK_UP then
      MoverFAT(ListView.Selected.Index, -1)
    else if Key = VK_DOWN then
      MoverFAT(ListView.Selected.Index, 1)
end;

procedure TForm6.MoverFAT(I, J: Integer);
begin
  if ((I + J) > -1) and ((I + J) < (FATs.Count)) then
  begin
    FATs.Exchange(I, I + J);
    ListView.Invalidate;
    ListView.Selected := ListView.Items[I + J];
  end;
end;

end.
于 2013-04-22T18:34:52.353 に答える