基本上我想要一个由StringList填充的ListView,当我选择一个ListItem并按向上或向下时,它会向上或向下移动项目(在两个列表中)。
我正在使用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;
答案 0 :(得分:3)
我使用以下Atualizer
实现重现了您的问题:
ListView.Clear;
for I := 0 to FATs.Count - 1 do
ListView.AddItem(FATs[I], nil);
(如果你也给了我们,那肯定会容易得多。)
问题是ListView本身会尝试处理密钥,但由于您(可能)删除了Atualizer
例程中的所有项目,因此它不知道如何操作。
通过分配0
告诉ListView它不应再处理键击来解决它:
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's comment中的虚拟方法。或者您也可以交换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;
答案 1 :(得分:2)
就NGLN已经指出问题而言,我建议采用另一种方法 不要将数据存储在Listview中,只需将其用于显示数据。 只需要一个未触及的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.