在添加到Tlistview之前检查TListItem重复

时间:2013-10-30 15:54:33

标签: delphi delphi-xe5 tlistview

我有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;,但这对我的用例没有帮助。我似乎无法找到上述内容的任何文档。

2 个答案:

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

使用您的代码,Ownernil,因此此代码只会导致访问冲突。实际上你不应该实例化TListItem。这是由容器类完成的。

即使没有这个问题,你会发现IndexOf没有做你想要的。您希望它对项目的执行搜索。但它会对引用执行搜索。

您需要做的是遍历列表中的每个项目,并根据预期新值检查其标题和子项目(或标识项目的任何内容)。

如果您想要进行更激烈的改变,那么从长远来看会让生活变得更轻松,并且如果列表变大则提高性能,那么在虚拟模式下切换到使用列表视图会有所帮助。您需要在TList<TMyItem>或类似内容中保留商品列表。然后你会按需填充。如果你这样做,那么检测重复项会更容易,因为你正在使用普通容器而不是GUI控件。从根本上说,通过将GUI控件用作容器类,您将为自己的生活变得艰难。

答案 1 :(得分:0)

我建议您将主要记录列表排序到第二个列表中,该列表中已过滤掉重复项,然后使用第二个列表填充ListView。我还建议在虚拟模式下使用ListView(将其OwnerData属性设置为true,然后使用其OnData ...事件)。这将极大地提高ListView的性能,然后您可以在内存中访问/操作您的记录,而不会被UI减慢。