Firemonkey ListView item indexes not updating

感情迁移 提交于 2019-12-08 04:55:16

问题


I'm using a TListView in Firemonkey. On startup, I create 3 list view headers and keep references to them for future use (specifically inserting items below each header).

FItemHeader:= LV.Items.Add;
FItemHeader.Purpose:= TListItemPurpose.Header;
FItemHeader.Text:= 'Items';
FChargeHeader:= LV.Items.Add;
FChargeHeader.Purpose:= TListItemPurpose.Header;
FChargeHeader.Text:= 'Charges';
FPaymentHeader:= LV.Items.Add;
FPaymentHeader.Purpose:= TListItemPurpose.Header;
FPaymentHeader.Text:= 'Payments';

Then, I've added a few items below the first (Item) header, which works fine.

SomeItem:= LV.Items.Insert(FChargeHeader.Index);

Then later, I wish to insert an item below one of the other headers...

SomeItem:= LV.Items.Insert(FPaymentHeader.Index);

This is supposed to add the item just above the Payments Header (last item in the Charges section). However, it instead gets added further up the list (at index 2).

While debugging this issue, it came as a surprise that the 3 headers' indexes have not been updated after adding items. The following code demonstrated that:

S:= 'Items: '+IntToStr(FItemHeader.Index)+sLineBreak+
  'Charges: '+IntToStr(FChargeHeader.Index)+sLineBreak+
  'Payments: '+IntToStr(FPaymentHeader.Index);
ShowMessage(S);

The indexes were 0, 1, and 2 even though they're supposed to be larger (after adding some items).

Further debugging led me to add this code:

for X := 0 to LV.Items.Count-1 do begin
  S:= S + LV.Items[X].Text+' - '+IntToStr(LV.Items[X].Index)+sLineBreak;
end;
ShowMessage(S);

Which reports all the correct indexes. Further, if I call this second piece of code and then the first piece, the indexes are fine..

for X := 0 to LV.Items.Count-1 do begin
  S:= S + LV.Items[X].Text+' - '+IntToStr(LV.Items[X].Index)+sLineBreak;
end;
ShowMessage(S);
S:= 'Items: '+IntToStr(FItemHeader.Index)+sLineBreak+
  'Charges: '+IntToStr(FChargeHeader.Index)+sLineBreak+
  'Payments: '+IntToStr(FPaymentHeader.Index);
ShowMessage(S);

So after a bit more digging, it turns out a simple call to...

LV.Items[1].Index;

...forced that particular item to be re-indexed.

While technically this works, it's an extremely sloppy work-around. What else can I do to ensure this list view gets re-indexed prior to inserting an item?

NOTE: When I did a similar approach using a TListBox I did not have this issue. It's surely a bug in the TListView control. I'm not asking how to fix the bug, but for a better work-around.

NOTE: This work-around only appeared to work once or twice - further attempts and even this work-around doesn't force a re-index.

UPDATE

It seems that this is the only magical work-around, which is still very sloppy:

procedure ReindexListView(AListView: TListView);
var
  X: Integer;
begin
  for X := 0 to AListView.Items.Count-1 do
    AListView.Items[X].Index;
end;

回答1:


This is bug in Delphi XE8. Works fine in Delphi XE7 Update 1.

Read more about bug: Delphi XE8 bug in TList<T>, need workaround


Really looks like a bug. Tested with Delphi XE8 under Win32 and Win64.

Method .AddItem has the same effect like .Insert

How it looks:

How it should be (and how it looks if you are using LV.Items[1].Index). NOTE: The same effect if prior adding item under "Charges" you going to select any item in TListView




回答2:


While the real fix is in Embarcadero's ball court, this seems to be the only work-around:

procedure ReindexListView(AListView: TListView);
var
  X: Integer;
begin
  for X := 0 to AListView.Items.Count-1 do
    AListView.Items[X].Index;
end;

Behind the scenes, there is a known bug in the generic TList implementation, specifically a mis-hap with the Insert function. I haven't confirmed whether this is the case or not, but this work-around does the trick at least.



来源:https://stackoverflow.com/questions/30850911/firemonkey-listview-item-indexes-not-updating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!