Without the BeginUpdate/EndUpdate the following code works OK
list.BeginUpdate;
with list.Items do try
Clear;
for var c in qus do
with add do begin
text:='some text';
DataObject:=c;
end;
list.EndUpdate;
Assert(list.itemindex<=list.Items.Count);
We have tested this here and don't get an error. I'm not sure what c & qus is and how many items are added? Also, are there items added before clearing the list? Please provide more details.
- It happens in VCL but I noticed the same in FMX
- qus is a
Tlist<Tsomethingobject>
, so c is the Tsomethingobject
- Yes, usually there are items before clearing the list
It happens (Itemindex has a wrong value) in
procedure TTMSFNCCustomListBox.EndUpdate;
begin
inherited;
if Assigned(FTreeView) then
begin
Dec(FUpdateCount);
FTreeView.EndUpdate;
SelectedItem := FSaveSelectedItem;
end;
end;
after the FTreeView.EndUpdate;
We'll further investigate this here, in the meantime you can manually set the value to make sure it lies within the items count.
Try the following code, keep pressing the button until you get the error
unit Unit4;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VCL.TMSFNCTypes, VCL.TMSFNCUtils,
VCL.TMSFNCGraphics, VCL.TMSFNCGraphicsTypes, Vcl.StdCtrls,
VCL.TMSFNCCustomControl, VCL.TMSFNCListBox;
type
TForm4 = class(TForm)
list: TTMSFNCListBox;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
procedure TForm4.Button1Click(Sender: TObject);
begin
list.BeginUpdate;
with list.Items do try
Clear;
for var n:=0 to trunc(random(20))+1 do
with add do begin
text:='some text '+n.ToString+'<br>something';
end;
finally list.EndUpdate; end;
Assert(list.itemindex<=list.Items.Count);
if (list.Items.Count>0) and (list.ItemIndex<0) then list.SelectItem(0);
end;
end.
You will notice also that sometimes, with items inside the Listbox, the first item is not selected as expected by the above code
It tries to preserve the item and then resets it, but unfortunately the current implementation does not take Clearing into account, so for now, please set the ItemIndex to 0, or to a value within the Item count, to make sure that the error does not occur.
The same problem happens sometimes with list.SelectedItem:=something;
Did you reproduced the initial Endupdate problem?
Thank you in advance
The TTMSFNCListBox.ItemIndex in many cases returns values bigger than TTMSFNCListBox.items.count.
It does not happen only with Endupdate, finally.
Not checking it always before using it, it makes the TTMSFNCListBox unusable.
I have created a class helper till having a fix.
Did someone else have the same problem?
It's unclear exactly what you mean. The code clears all the items, which means that the ItemIndex is invalid at that point. You know how many items you add after the clear, so you can just add:
list.BeginUpdate;
with list.Items do
try
Clear;
for var n := 0 to trunc(random(20)) + 1 do
with add do
begin
text := 'some text ' + n.ToString + '<br>something';
end;
finally
list.EndUpdate;
// list.ItemIndex := 0;
// or
// list.ItemIndex := List.Items.Count - 1
end;
I can't see a reason why ItemIndex would return an invalid value after forcing it to a value within Items.Count.
Finishing a project and using many TTMSFNCListBox I am getting a lot of sporadic errors that all of them are due to Itemindex values that are bigger than the items.count. It is not a problem of Endupdate as I can figure now. I had the same strange problems when trying to use it last month in FMX but I finally substituted with an other Listbox component.
Today with the following class helper and using only Itemindex for setting selected item everything works OK.
unit fnclistboxfake;
interface
uses VCL.TMSFNCListBox;
type TTTMSFNCListBoxfake=class helper for TTMSFNCListBox
public
function Itemindex2:integer;
end;
implementation
{ TTTMSFNCListBoxfake }
function TTTMSFNCListBoxfake.Itemindex2: integer;
begin result:=itemindex; if result>=items.Count then result:=-1; end;
end.
I do not know what I can do more to help for correcting this issue.
I already acknowledged that the BeginUpdate & EndUpdate does not take a Clear into account, so for now, manually setting the ItemIndex will fix the issue. We have internally added the necessary checks to make sure ItemIndex is not out of bounds, the next version will have this included.
1 Like