我有records
的列表,我想将其汇总为TListView
记录的结构如下
MyRecord = record
SourceTable: string;
SourceField: string;
TargetTable: string;
TargetField: string;
end;
在记录中可能有多个SourceTable / TargetTable实例,其中包含源/目标字段的单个实例
我想在vsReport样式中创建一个TListView
,它总结了每个SourceTable \ TargetTable对。
理想情况下,我想做以下事情:
procedure SetTables;
var
mp: MyPointer;
LI: TListItem;
begin
LI := LI.Create(nil);
LI.Caption := ap^.SourceTable;
LI.SubItems.Add(ap^.TargetTable);
LI.Checked := not ap^.Updated;
if lvMigration.Items.IndexOf(LI) = -1 then
lvMigration.Items.AddItem(LI);
end;
即。创建一个独立的TListItem,检查它是否已经存在,然后将其添加到我的TListView。然而,它在LI.Caption
的分配中断了 - 基本上没有任何东西要分配。我怀疑至少部分问题是(nil)
TListItem的正常创建是使用LI := lvMigration.Items.Add;
,但这对我的用例没有帮助。我似乎无法找到上述内容的任何文档。
答案 0 :(得分:1)
而不是:
LI := LI.Create(nil);
你打算写
LI := TListItem.Create(nil);
这是书中最古老的Delphi错误,我相信你之前已经做过(我们都有),而且我确定你看到它时就认出来了。
其余的代码不起作用。如果不提供TListItem
,您无法对Owner
实例执行任何操作。例如,查看TListItem.SetCaption
:
procedure TListItem.SetCaption(const Value: string);
begin
if Value <> Caption then
begin
FCaption := Value;
if not Owner.Owner.OwnerData then
....
end;
end;
使用您的代码,Owner
为nil
,因此此代码只会导致访问冲突。实际上你不应该实例化TListItem
。这是由容器类完成的。
即使没有这个问题,你会发现IndexOf
没有做你想要的。您希望它对项目的值执行搜索。但它会对引用执行搜索。
您需要做的是遍历列表中的每个项目,并根据预期新值检查其标题和子项目(或标识项目的任何内容)。
如果您想要进行更激烈的改变,那么从长远来看会让生活变得更轻松,并且如果列表变大则提高性能,那么在虚拟模式下切换到使用列表视图会有所帮助。您需要在TList<TMyItem>
或类似内容中保留商品列表。然后你会按需填充。如果你这样做,那么检测重复项会更容易,因为你正在使用普通容器而不是GUI控件。从根本上说,通过将GUI控件用作容器类,您将为自己的生活变得艰难。
答案 1 :(得分:0)
我建议您将主要记录列表排序到第二个列表中,该列表中已过滤掉重复项,然后使用第二个列表填充ListView。我还建议在虚拟模式下使用ListView(将其OwnerData属性设置为true,然后使用其OnData ...事件)。这将极大地提高ListView的性能,然后您可以在内存中访问/操作您的记录,而不会被UI减慢。