ListView没有选择正确的行

时间:2013-04-22 17:57:14

标签: delphi listview pascal

基本上我想要一个由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;

2 个答案:

答案 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.