Marsil 5 Posted 9 hours ago (edited) Hi, I have a ListView with CheckBoxes enabled (CheckBoxes = True) and an OnItemChecked event handler, if I try to add an item to the ListView: var Item := ListView1.Items.Add; // this immediately triggers OnItemChecked Item.Data := SomeLinkedObject; Item.Checked := SomeLinkedObject.Enabled; the OnItemChecked event handler is called immediatley not giving me a chance to assign the Item.Data property. The handler is procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); begin if not Assigned (Item.Data) then Memo1.Lines.Add ('ListView1ItemChecked called with nil Data '); // this debug always executed with nil data TSomeLinkedObject (Item.Data).Enabled := Item.Checked // AV here when ListView1.Items.Add executed end; Any idea why this is happening? or is it a bug? Edited 9 hours ago by Marsil Share this post Link to post
Remy Lebeau 1612 Posted 6 hours ago (edited) The checkboxes are implemented as state images. You are getting the event when the item's initial state is assigned. Just check for the nil condition and don't access the object when it's not ready yet: procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); begin if Assigned(Item.Data) then TSomeLinkedObject(Item.Data).Enabled := Item.Checked; end; Alternatively, disable the event when adding an item, and then re-enable the event when ready: ListView1.OnItemChecked := nil; var Item := ListView1.Items.Add; ... ListView1.OnItemChecked := ListView1ItemChecked; Edited 6 hours ago by Remy Lebeau 1 Share this post Link to post
Marsil 5 Posted 4 hours ago Thanks Remy, I implemented the first workaround. But I still don't understand why the ListView is firing the checked event for an item that still being created and still not properly initialized yet?😕 this behavior was really unexpected I always use VirtualTreeView, but this time I decided to use ListView because it will only contain just one or two items, a quick lightweight job. Share this post Link to post
Kas Ob. 143 Posted 3 hours ago 38 minutes ago, Marsil said: that still being created and still not properly initialized yet? But, it is already created, initialized (with default) and added with ListView1.Items.Add Your next Item.Checked := SomeLinkedObject.Enabled; Is triggering the event as designed, nothing wrong here, If you don't want that behavior, then try to create the item as local var, not by calling Items.Add then set (Initialize) properties and only then add it to the items, though i am not sure if this will trigger the event or not, it shouldn't, but who knows you need to test it, this will change the narrative of the expected behaviour and might, i say might, be discussed as bug or short in design, if just adding an item triggers an event. 1 Share this post Link to post
Marsil 5 Posted 2 hours ago (edited) 23 minutes ago, Kas Ob. said: But, it is already created, initialized (with default) and added with ListView1.Items.Add I mean my own initialization! 23 minutes ago, Kas Ob. said: Your next Item.Checked := SomeLinkedObject.Enabled; Is triggering the event as designed, nothing wrong here, No, the OnItemChecked event is triggered by this statement var Item := ListView1.Items.Add; // this immediately triggers OnItemChecked As I explained in the comment, I tried and removed the Item.Checked := SomeLinkedObject.Enabled; and same problem!! 23 minutes ago, Kas Ob. said: If you don't want that behavior, then try to create the item as local var, not by calling Items.Add then set (Initialize) properties and only then add it to the items, though i am not sure if this will trigger the event or not, it shouldn't, but who knows you need to test it, this will change the narrative of the expected behaviour and might, i say might, be discussed as bug or short in design, if just adding an item triggers an event. Thanks!, I will try what you suggested here! Edited 2 hours ago by Marsil Share this post Link to post
Marsil 5 Posted 1 hour ago 50 minutes ago, Kas Ob. said: If you don't want that behavior, then try to create the item as local var, not by calling Items.Add then set (Initialize) properties and only then add it to the items, though i am not sure if this will trigger the event or not, it shouldn't, but who knows you need to test it, this will change the narrative of the expected behaviour and might, i say might, be discussed as bug or short in design, if just adding an item triggers an event. I tried this var Item := TListItem.Create (ListView1.Items); Item.Caption := SomeLinkedObject.Name; Item.Checked := SomeLinkedObject.Enabled; Item.Data := SomeLinkedObject; ListView1.Items.AddItem (Item); but the item is shown without caption!, and memory leak occurred! --------------------------- Unexpected Memory Leak --------------------------- An unexpected memory leak has occurred. The unexpected small block leaks are: 13 - 20 bytes: TList x 4, Unknown x 4 21 - 28 bytes: UnicodeString x 3 37 - 44 bytes: UnicodeString x 1 45 - 52 bytes: TListItem x 4 77 - 84 bytes: TSubItems x 4 I don't think solves the issue since the only way to implement your suggestion is to use ListView.Items.AddItem which is called by ListView.Items.Add. 1 Share this post Link to post
Kas Ob. 143 Posted 1 hour ago You are right the the behavior is wrong and buggy, Using similar approach of create then add, doesn't show caption, but no memory leak on XE8. Share this post Link to post
Kas Ob. 143 Posted 1 hour ago Debugging and tracking the OnChecked event, the behavior has nothing to do with Delphi and its VCL, it is triggered by Windows message, so you have to use a workaround about that, something like what Remy suggested. Share this post Link to post