Tang 1 Posted November 9, 2021 I built a multi-device app using FireMonkey. I have a ListView Live-Binding to a DB. Both synched by *. It all works normally until I left wipe an item to delete. The item can be deleted, but the DB record is not. So following Doug Rudd advice, implemented following code to store DBID and locate the deleting Item. procedure TPassPlus.LinkListControlToField1FilledListItem(Sender: TObject; const AEditor: IBindListEditorItem); begin (AEditor.CurrentObject as TListItem).Tag := DB_Table.FieldByName('DBID').AsInteger; end; myDBID:= ListView1.Selected.Tag.ToString; if DB_Table.Locate('DBID',myDBID,[]) then DB_Table.delete; It worked well to delete the DB record. However, when ListView1DeletingItem event finished, it generated a 'Argument out of range' error, which can be traced into TPresentedListView.DoDeleteItem event. It looks like, when DB record deleted, Listview has deleted the correspoding item, so when ListView1DeletingItem event finished, ListView has nothing to delete. What is the solution? I was trying to decouple the link between the DB and Listview at runtime so I can delete the record and re-link the two. I tried following code as a test. procedure TPassPlus.ListView1DeletingItem(Sender: TObject; AIndex: Integer; var ACanDelete: Boolean); begin ListView1.BeginUpdate; BindSourceDB1.DataSource.DataSet.close; //or LinkListControlToField1.Active:=false; ListView1.EndUpdate; end; On either case, it will produce 'Argument out of range' error. What is the way to do this simple task? Share this post Link to post
Serge_G 87 Posted November 10, 2021 Hi, Well, I don't understand the goal, I never use this DeletingItem method, but I will investigate. So to be clear : You have a TListView filled with livebindings, how do you : 14 hours ago, Tang said: I left wipe an item to delete. A gesture, I think, but the code? (I am not a gesture expert) Sorry to disappoint, but I'm not that far (I have not encountered this need in my professional life) Share this post Link to post
Uwe Raabe 2057 Posted November 10, 2021 Wipe Left to Delete is a standard functionality in FMX-TListView. Share this post Link to post
Serge_G 87 Posted November 10, 2021 51 minutes ago, Uwe Raabe said: Wipe Left to Delete Ok, but I try this on a windows pc how can I "simulate" this wipeleft ? On another hand, with a "classic" windows app (D11 Alexandria). I found that Deleting last item of the list raise an 'access violation' ! procedure TForm1.LinkListControlToField1FilledListItem(Sender: TObject; const AEditor: IBindListEditorItem); begin (AEditor.CurrentObject as TListItem).Tag := FDTable1.FieldByName('ID').AsInteger; end; procedure TForm1.ListView1ButtonClick(const Sender: TObject; const AItem: TListItem; const AObject: TListItemSimpleControl); begin if FDtable1.Locate('Id',AItem.Tag) then FDtable1.Delete; end; Share this post Link to post
Serge_G 87 Posted November 10, 2021 (edited) So, I test this on Android. @Tang I can submit you this solution Add a private variable (in my code key : integer;) procedure TForm1.ListView1DeleteItem(Sender: TObject; AIndex: Integer); begin if FDMemtable1.Locate('id',key) then fdmemtable1.Delete; // delete the record end; procedure TForm1.ListView1DeletingItem(Sender: TObject; AIndex: Integer; var ACanDelete: Boolean); begin key:=listView1.Items[aIndex].Tag; // get the key to delete ACandelete:=true; end; But, yes, there is one, I think there is a bug I wrote in the prior post : 23 hours ago, Serge_G said: Deleting last item of the list raise an 'Out of range' error ! Edited November 11, 2021 by Serge_G not an 'access violation' error but an 'Out of range' one Share this post Link to post
Rollo62 536 Posted November 10, 2021 6 hours ago, Uwe Raabe said: Wipe Left to Delete is a standard functionality in FMX-TListView. The "wipe-left" feels also not very iOS-UX-standard-like, that is what my clients complain. So I tried to remove that, by some other methods. Share this post Link to post
Tang 1 Posted November 11, 2021 (edited) Thanks Serge, Indeed, it worked for me as well. It means ListView1DeletingItem is only for retrieving the DB record 'id' which is bound to the deleting ListView.Items[AIndex] and ListView1DeleteItem is for DB delete work. For my case, when I delete the DB record, my ListView has no data to show. So, I have to close and reopen the DB to let the ListView to show the data. Not sure if you had similar issue. The whole point of this question is to find a way , when user delete a Listview item, it will also safely delete the livebinding DB record. I thought this is very straight forward operation. In fact, Item.delete is not linked to DB record deleting automatically. I guess this is about LinkListControlToField1. This is a one way binding, not bi-directional. So. cause the trouble. And in ListView1DeletingItem event, we cannot do any deletion, it will cause many different kinds of error because the ListView index and DB record index. If you have a search box working, things will get more complicated. Here, we can only get a DBID related to the deleting Item. then in ListView1DeleteItem event do the DB.delete. It seems working now, thanks for all your helps. I did not have a 'access violation' ! error when delete the last record. But I did see some posts mentioned similar issue. Maybe need BeginUpdate/EndUpdate? 'wipe-left' is quite handy for deletion. For instance, on iOS Notification Page, you will receive many notifications from various APPs. They can be wiped off. Email App uses this to delete email. But I guess Serge's delete button seems not a native FMX ListView delete button. Did you added by your own? That may cause the ‘access error’. You can only wipe one item therefore, only 1 button will be shown. Yours shows all the buttons. My APP's Listview is here. It works on windows and mobile OS consistently. Edited November 11, 2021 by Tang 1 Share this post Link to post
Serge_G 87 Posted November 11, 2021 (edited) 8 hours ago, Tang said: But I guess Serge's delete button seems not a native FMX ListView delete button. Did you added by your own? That may cause the ‘access error’. Hi, No, the image I post was a "classic" ImageListItemRightButton Item appearance (with TextButton visible) , and ImageListItemRightButtonDelete for the ItemEdit appearance. The "access error", I got it when I try to use a ListView1.DeleteItem(AItem.Index); beforehand declared as an helper (only way I found to raise OnDelete/Ondeleting event with touch input unavailable. TListViewHelper = class helper for TListView public function DeleteItem(const ItemIndex: Integer): Boolean; end; { TListViewHelper } function TListViewHelper.DeleteItem(const ItemIndex: Integer): Boolean; begin inherited; end; And using the OnButtonClick event of TListView (guilt, the TListItem.MouseUp event) Using the OnItemClick to use DeleteItem procedure TForm1.ListView1ItemClick(const Sender: TObject; const AItem: TListViewItem); begin ListView1.DeleteItem(AItem.Index); end; I have no "access error" 8 hours ago, Tang said: I did not have a 'access violation' ! error when delete the last record. But I did see some posts mentioned similar issue. Sorry, it was an "argument out of range" not an "access violation" (guilty TListItemView.GetObject). My test (on Android), shows me that if there is only one item (the one to delete) this exception does not raise. 8 hours ago, Tang said: Maybe need BeginUpdate/EndUpdate? Yes, perhaps a bypass but in wich event ? Edited November 11, 2021 by Serge_G Share this post Link to post
Serge_G 87 Posted November 11, 2021 8 hours ago, Tang said: It means ListView1DeletingItem is only for retrieving the DB record 'id' which is bound to the deleting ListView.Items[AIndex] and ListView1DeleteItem is for DB delete work. Yes, but if I do so, it's because the AIndex argument of OnDelete event is always 0 ! (what a strange thing no ?) Share this post Link to post
Tang 1 Posted November 11, 2021 I think that is the Pro and Con for LiveBinding. It is easy to use but with bugs or big improvement space. It handles the link, update, delete, index etc between Listview and the datasource. We cannot do any change, otherwise it will mess up the relationships between the 2 easily. ListView1DeleteItem event is the place where we can 'change' work. But occasionally, I will have 'access violation error'. I am still not figuring out when and why, error not reproducible. Share this post Link to post
Tang 1 Posted November 11, 2021 14 minutes ago, Serge_G said: Yes, but if I do so, it's because the AIndex argument of OnDelete event is always 0 ! (what a strange thing no ?) ListView1DeletingItem already deleted the Listview.item[AIndex]. then it comes to ListView1DeleteItem so, here AIndex is always 0, ( guess being reset after the ListItem was deleted). So, we need to get the DB id associated with the ListItem in ListView1DeletingItem event. In this event, we still have the Item and its Tag ... 1 Share this post Link to post
codeGood 0 Posted November 21, 2022 Tang, I'm struggling with the same issue. If you managed to do anything about it I would greatly appreciate it if you can share it with me or workaround around this. Thanks Share this post Link to post