我尝试为每个选定的列表项做一个动作,但它不起作用。 这就是我的尝试:
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条消息,我该如何解决?
答案 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
则会展开更多选定项目。
如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;