Delphi Firemonkey TListView.selected 在 onItemsChange 中始终为 nil

Delphi Firemonkey TListView.selected is always nil in onItemsChange

Firemonkey 应用程序,Windows 和 MacOS 目标。

我需要知道当用户使用光标键滚动或用鼠标单击列表视图项目时选择了什么项目。

我可以通过 onItemClick 事件对鼠标单击做出反应,这很好,当我使用光标键移动选择时也会触发 onItemsChange 事件,但列表视图的选定 属性 始终保持在在该事件中为零。

这是一个错误还是我遗漏了什么?

当用户在控件中使用光标键时,我如何知道选择了什么项目?

您使用了错误的事件。 OnItemsChange 事件是

Event that occurs after a list of items has been changed.

as the documentation states。您是否更改项目列表?不,你不知道。

您要找的是OnChange活动:

Occurs when the ItemIndex property changes as a result of a user selecting a different item. Write an OnChange event handler to respond to changes of the ItemIndex property. OnChange allows a response once the list has been successfully changed.

参见documentation for more details

我真的不明白他们到底是个反对票???大部头书。但是我决定更新我的答案并尝试让它更清楚

首先:您需要意识到 OnChange 事件并不是您可以在 上执行此操作的唯一事件.真正的问题是为什么 GetSelected getter 方法在 OnItemsChange 事件和 returns nil.

上失败

selected属性的声明是这样的

property Selected: TListItem read GetSelected write SetSelected;

对其 getter 方法的检查是这样的:

if (FItemIndex >= 0) and (FItemIndex < Adapter.Count) then 
    return code
else
    result := nil;

很明显有事情发生了

documentation

List item that is currently selected on the list view. This property is nil if no item is selected.

by selected 他们指的是上面的检查。这引发了以下问题,首先是如何触发此事件的。在 documentation 它说

Event that occurs after a list of items has been changed.

这意味着当你改变项目的存在时(删除、添加而不改变高度或宽度我已经检查过了)。此外,如果事件不改变 selection

,selected 属性 不会 return nil

可以使用以下测试

在表格中添加以下内容

  • TListView
  • TCheckBox
  • 一个 TButton

在按钮的OnClick事件中添加这个

procedure TForm5.Button1Click(Sender: TObject);
var
  I: Integer;
begin
for I := 1 to 10 do
listview1.items.add;
end;

在 OnItemsChange 事件中添加这个

procedure TForm5.ListView1ItemsChange(Sender: TObject);
begin
caption := 'fired'+datetimetostr(now);
if checkbox1.IsChecked then
caption := 'selected item index: '+ inttostr(listview1.Selected.index);
end;

您得到以下结果

  • 第一次用 CheckBox.IsChecked = True 添加项目(没有 selected 因为没有项目)你会得到一个 AV,因为没有什么可以 selected
  • 成功添加未选中复选框的项目后 select 并选中该复选框,然后添加另一个项目。瞧,没有 AV

在我看来,我认为你属于第一种情况(这很奇怪,你没有调查原因)。

撇开文档中关于 OnChange 事件的内容不谈。只要您确保 一个项目在调用 GetSelected 方法之前被 select 编辑,您就不会拥有 AV。

最后: 我发现人们没有付出额外的努力来回答 为什么 问题真的很令人失望。

如果你不知道它失败的原因,那么如何确保它不会再次失败?