对于每个选定的列表项目

时间:2014-03-04 18:05:21

标签: delphi listview listitem

我尝试为每个选定的列表项做一个动作,但它不起作用。 这就是我的尝试:

var
TLsttem:TListItem;
begin
for TLsttem in form1.listview1.Selected do
begin
...
end;
end;

现在我收到了这个错误:

  

[dcc32错误] MSGBox.pas(50):E2431 for-in语句无法操作   集合类型'TListItem',因为'TListItem'不包含   “GetEnumerator”的成员,或者无法访问

我该如何解决这个问题?

编辑: 我现在尝试了这个脚本:

TLsttem := form1.ListView1.Selected;
    while TLsttem <> nil do
    begin
    showmessage('Test');
    TLsttem := form1.ListView1.GetNextItem(TLsttem, sdAll, [isSelected]);
  end;

但我只收到1条消息,我该如何解决?

3 个答案:

答案 0 :(得分:9)

此示例来自文档GetNextItem

procedure TForm1.Button1Click(Sender: TObject);
var
  Item: TListItem;
begin
  Item := ListView1.Selected;
  while Item <> nil do
  begin
    ListBox1.Items.Add(Item.Caption);
    Item := ListView1.GetNextItem(Item, sdAll, [isSelected]);
  end;
end; 

TListView.Selected获取第一个选定项目,而GetNextItem则会展开更多选定项目。

enter image description here


如David所述,可以将此逻辑包装到枚举器中,以便可以使用for .. in循环。 最简单的方法是将此枚举放入类助手中,就像@StefanGlienke的答案一样。

type
  TSelectedListItemsEnumerator = record
  private
    FListView: TListView;
    FItem: TListItem;
  public
    constructor Create(aListView: TListView);
    function GetEnumerator: TSelectedListItemsEnumerator;
    function MoveNext: Boolean;
    property Current: TListItem read FItem;
  end;

  TListViewHelper = class helper for TListView
  private
    function GetSelectedItems: TSelectedListItemsEnumerator;
  public
    property SelectedItems: TSelectedListItemsEnumerator
      read GetSelectedItems;
  end;

{ TSelectedListItemsEnumerator }

constructor TSelectedListItemsEnumerator.Create(aListView: TListView);
begin
  FListView := AListView;
end;

function TSelectedListItemsEnumerator.GetEnumerator: TSelectedListItemsEnumerator;
begin
  FItem := nil;
  Result := Self;
end;

function TSelectedListItemsEnumerator.MoveNext: Boolean;
begin
  FItem := FListView.GetNextItem(FItem,sdAll,[isSelected]);
  Result := (FItem <> nil);
end;

{ TListViewHelper }

function TListViewHelper.GetSelectedItems: TSelectedListItemsEnumerator;
begin
  Result := TSelectedListItemsEnumerator.Create(Self);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Item: TListItem;
begin
  for Item in ListView1.SelectedItems do
  begin
    Memo1.Lines.Add(Item.Caption);
  end;
end;

答案 1 :(得分:5)

虽然对于这个例子来说,这可能是一种过度杀戮,这是一种使用可以使用for-in循环枚举的SelectedItem属性扩展TListView类的方法。

如果循环中的条件可能比仅检查属性或实际提供过滤器委托更复杂,则这可能非常强大。

type
  TSelectedListItemsEnumerator = class(TListItemsEnumerator)
  public
    function MoveNext: Boolean;
  end;

  TSelectedListItemsEnumerable = record
  private
    FListItems: TListItems;
  public
    constructor Create(AListItems: TListItems);
    function GetEnumerator: TSelectedListItemsEnumerator;
  end;

  TListViewHelper = class helper for TListView
  private
    function GetSelectedItems: TSelectedListItemsEnumerable;
  public
    property SelectedItems: TSelectedListItemsEnumerable
      read GetSelectedItems;
  end;

{ TSelectedListItemsEnumerator }

function TSelectedListItemsEnumerator.MoveNext: Boolean;
begin
  repeat
    Result := inherited;
  until not Result or Current.Selected;
end;

{ TSelectedListItemsEnumerable }

constructor TSelectedListItemsEnumerable.Create(AListItems: TListItems);
begin
  FListItems := AListItems;
end;

function TSelectedListItemsEnumerable.GetEnumerator: TSelectedListItemsEnumerator;
begin
  Result := TSelectedListItemsEnumerator.Create(fListItems);
end;

{ TListViewHelper }

function TListViewHelper.GetSelectedItems: TSelectedListItemsEnumerable;
begin
  Result := TSelectedListItemsEnumerable.Create(Items);
end;

然后您可以像这样使用它:

procedure TForm1.Button1Click(Sender: TObject);
var
  item: TListItem;
begin
  for item in ListView1.SelectedItems do
  begin
    ShowMessage(item.Caption);
  end;
end;

答案 2 :(得分:3)

在XE5(VCL)中,这对我来说非常合适:

var
  Item: TListItem;
begin
  for Item in ListView1.Items do
  begin
    if Item.Selected then
    begin
      // Do something with the item
    end;
  end;
end;