如何将项目添加到TListView时捕获事件?
根据文档,我认为OnInsert
事件可以完成这项工作。它甚至将实际的TListItem
对象传递给处理程序:
OnInsert 在将新项目插入列表后立即发生 图。
编写一个OnInsert事件处理程序,以便在项刚刚出现时进行响应 添加到列表中。 Item参数是TListItem对象 添加到Items属性
这是我的代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
with ListView1.Items.Add do
begin
Caption := 'foo';
SubItems.Add('bar');
end;
end;
procedure TForm1.TListView1Insert(Sender: TObject; Item: TListItem);
begin
//Item is empty
ShowMessage(Item.Caption);
end;
但令人惊讶的是,Item.Caption
总是空的。对我来说似乎是胡说八道。
修改
按照建议切换到Items.AddItem()
会导致另一个奇怪的问题。
OnInsert
事件处理程序现在按预期工作,但TListView
不显示TListItem.Caption
。
procedure TForm1.Button1Click(Sender: TObject);
begin
with ListView1.Items.Add do
begin
Caption := 'foo1';
SubItems.Add('bar1');
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
item: TListItem;
begin
item := TListItem.Create(ListView1.Items);
item.Caption := 'foo2';
item.Subitems.Add('bar2');
ListView1.Items.AddItem(item);
end;
procedure TForm1.ListView1Insert(Sender: TObject; Item: TListItem);
begin
//this now works as expected
ShowMessage(Item.Caption);
end;
为什么会这样?
答案 0 :(得分:7)
当新项目添加到ListView时,确实会触发TListView.OnInsert
事件。但是,Item
会在调用TListView.Items.Add()
时添加到ListView,而不会在Button1Click()
退出时添加。在OnInsert
仍在运行时,会调用Add()
事件处理程序(以响应LVN_INSERTITEM
通知)。因此,当然Item
事件处理程序中的OnInsert
将始终为空,因为您尚未为其分配任何值。
更新:将TListItem
添加到ListView时,未启用基础LVITEM
的LVIF_TEXT
标记。要显示TListItem.Caption
和TListItem.SubItems
文字,TListView
旨在依赖于ListView_SetItemText()
而LPSTR_TEXTCALLBACK
标志:
此参数可以是LPSTR_TEXTCALLBACK,以指示父窗口存储文本的回调项。在这种情况下,列表视图控件在需要文本时向父级发送
LVN_GETDISPINFO
通知代码。
如果您在TListItem.Caption
实际上尚未在ListView中分配TListItem.SubItems
或TListItem
属性,则LPSTR_TEXTCALLBACK
标志将不会应用于这些字段。如果没有LVN_GETDISPINFO
,TListView
将不会向LPSTR_TEXTCALLBACK
查询第1列的文本(因为第0列在OS层具有特殊含义),但它会查询第2列的文本列(即使未应用LPSTR_TEXTCALLBACK
)。这就是为什么您的第二个示例缺少UI中的'foo2'
标题文本,而不是'bar2'
文本。
实际的'foo2'
字幕字符串存储在TListItem
对象中,这就是ShowMessage()
能够正常工作的原因。
因此,如果您在将项目添加到ListView之前创建新的TListItem
并修改其Caption
,则必须手动调用ListView_SetItemText()
以启用{{1}标题的标志,例如:
LPSTR_TEXTCALLBACK
或者,暂时重置uses
Commctrl;
procedure TForm1.Button2Click(Sender: TObject);
var
item: TListItem;
begin
item := TListItem.Create(ListView1.Items);
item.Caption := 'foo2';
item.Subitems.Add('bar2');
ListView1.Items.AddItem(item);
ListView_SetItemText(ListView1.Handle, item.Index, 0, LPSTR_TEXTCALLBACK);
end;
属性值(属性设置器在调用Caption
之前检查重复的字符串):
ListView_SetItemText()
请注意,无论哪种方式,procedure TForm1.Button2Click(Sender: TObject);
var
item: TListItem;
begin
item := TListItem.Create(ListView1.Items);
item.Caption := 'foo2';
item.Subitems.Add('bar2');
ListView1.Items.AddItem(item);
item.Caption := '';
item.Caption := 'foo2';
end;
文字都会在首次调用TListItem.Caption
事件之后才会显示在用户界面中,因为它会在OnInsert
运行时触发。
我在XE2中重现了这一点。如果问题仍然发生在10.2东京,我会建议{Emborcadero filing a bug report。插入任何已经分配的字符串字段后,AddItem()
可能应该强制AddItem()
,或者至少LPSTR_TEXTCALLBACK
。