TListView:添加项目?
TListView: on item added?
当一个项目被添加到 TListView 时,我如何捕捉事件?
根据文档,我认为 OnInsert
事件可以完成这项工作。它甚至将实际的 TListItem
对象传递给处理程序:
OnInsert Occurs immediately after a new item is inserted into the list
view.
Write an OnInsert event handler to respond when an item has just been
added to the list. The Item parameter is the TListItem object that was
added to the Items property
这是我的代码:
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;
这是为什么?
TListView.OnInsert
事件确实是在ListView中添加新项时触发的。但是,Item
是在调用 TListView.Items.Add()
时添加到 ListView 的,而不是在 Button1Click()
退出时添加的。 OnInsert
事件处理程序被调用(响应 LVN_INSERTITEM
通知),而 Add()
仍然是 运行。因此,当然 OnInsert
事件处理程序中的 Item
将始终为空,因为您尚未为其分配任何值。
Update:当一个TListItem
添加到ListView时,底层LVITEM
is not enabled. To display the TListItem.Caption
and TListItem.SubItems
text, TListView
is designed to rely on ListView_SetItemText()
的LVIF_TEXT
标志与LPSTR_TEXTCALLBACK
标志改为:
This parameter can be LPSTR_TEXTCALLBACK to indicate a callback item for which the parent window stores the text. In this case, the list-view control sends the parent an LVN_GETDISPINFO
notification code when it needs the text.
如果您分配 TListItem.Caption
或 TListItem.SubItems
属性 而 TListItem
实际上尚未在 ListView 中,则 LPSTR_TEXTCALLBACK
标志将不会获得应用于那些领域。 LVN_GETDISPINFO
不会在 TListView
中查询没有 LPSTR_TEXTCALLBACK
的第 1 列的文本(因为第 0 列在 OS 层具有特殊含义),但它会查询第二列的文本(即使未应用 LPSTR_TEXTCALLBACK
)。这就是为什么您的第二个示例缺少 UI 中的 'foo2'
标题文本,而不是 'bar2'
文本。
实际的 'foo2'
字幕字符串存储在 TListItem
object 中,这就是为什么您的 ShowMessage()
能够工作的原因。
因此,如果您创建一个新的 TListItem
并在项目添加到 ListView 之前修改其 Caption
,您将必须手动调用 ListView_SetItemText()
以启用 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
属性 值(属性 setter 在调用 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
文本都不会出现在 UI 中,直到首先调用 OnInsert
事件之后,因为它是在 [=51= 时触发的] 是 运行.
我在 XE2 中复制了这个。如果问题仍然发生在 10.2 Tokyo 中,我建议使用 Embarcadero filing a bug report。 AddItem()
应该在插入任何 already-assigned 字符串字段后强制 LPSTR_TEXTCALLBACK
,或者至少 Caption
,无论如何。
当一个项目被添加到 TListView 时,我如何捕捉事件?
根据文档,我认为 OnInsert
事件可以完成这项工作。它甚至将实际的 TListItem
对象传递给处理程序:
OnInsert Occurs immediately after a new item is inserted into the list view.
Write an OnInsert event handler to respond when an item has just been added to the list. The Item parameter is the TListItem object that was added to the Items property
这是我的代码:
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;
这是为什么?
TListView.OnInsert
事件确实是在ListView中添加新项时触发的。但是,Item
是在调用 TListView.Items.Add()
时添加到 ListView 的,而不是在 Button1Click()
退出时添加的。 OnInsert
事件处理程序被调用(响应 LVN_INSERTITEM
通知),而 Add()
仍然是 运行。因此,当然 OnInsert
事件处理程序中的 Item
将始终为空,因为您尚未为其分配任何值。
Update:当一个TListItem
添加到ListView时,底层LVITEM
is not enabled. To display the TListItem.Caption
and TListItem.SubItems
text, TListView
is designed to rely on ListView_SetItemText()
的LVIF_TEXT
标志与LPSTR_TEXTCALLBACK
标志改为:
This parameter can be LPSTR_TEXTCALLBACK to indicate a callback item for which the parent window stores the text. In this case, the list-view control sends the parent an
LVN_GETDISPINFO
notification code when it needs the text.
如果您分配 TListItem.Caption
或 TListItem.SubItems
属性 而 TListItem
实际上尚未在 ListView 中,则 LPSTR_TEXTCALLBACK
标志将不会获得应用于那些领域。 LVN_GETDISPINFO
不会在 TListView
中查询没有 LPSTR_TEXTCALLBACK
的第 1 列的文本(因为第 0 列在 OS 层具有特殊含义),但它会查询第二列的文本(即使未应用 LPSTR_TEXTCALLBACK
)。这就是为什么您的第二个示例缺少 UI 中的 'foo2'
标题文本,而不是 'bar2'
文本。
实际的 'foo2'
字幕字符串存储在 TListItem
object 中,这就是为什么您的 ShowMessage()
能够工作的原因。
因此,如果您创建一个新的 TListItem
并在项目添加到 ListView 之前修改其 Caption
,您将必须手动调用 ListView_SetItemText()
以启用 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
属性 值(属性 setter 在调用 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
文本都不会出现在 UI 中,直到首先调用 OnInsert
事件之后,因为它是在 [=51= 时触发的] 是 运行.
我在 XE2 中复制了这个。如果问题仍然发生在 10.2 Tokyo 中,我建议使用 Embarcadero filing a bug report。 AddItem()
应该在插入任何 already-assigned 字符串字段后强制 LPSTR_TEXTCALLBACK
,或者至少 Caption
,无论如何。