grantful 3 Posted August 12, 2023 I am trying to show only the records based on the item i click in a listbox. on the onclick item i have procedure TForm2.ListBox1ItemClick(const Sender: TCustomListBox; const Item: TListBoxItem); var drinkid: Integer; begin FDQuery1.SQL.Clear; FDQuery1.SQL.Text := ('select idDrink from drinks where idDrink = :idDrink '); drinkid := FDQuery1.FieldByName('idDrink').AsInteger := listbox1.ItemIndex; showmessage(intToStr(drinkid)); FDQuery1.Open; TabControl1.ActiveTab := TabItem8; end; so if i make this query in the fdQuery1 sql and exacute it all looks good. here is the drinklist listbox I need to replace the From drinks where idDrink = 12910 with the record that is clicked on in the listbox. The detail on the right is the idDrink for each record. I am not sure i am going about this the right way. Thanks for any help with the correct code to get this to work. Share this post Link to post
Stano 143 Posted August 12, 2023 You're going down a very bad road. ItemIndex has no meaningful value. I don't know TCustomListBox at all. I assume it has Items, which is a child of TString. It does the following: Name: string; ID: T.. - some class from TObject into which you can put an integer. Items.AddObject(Name, ID); You use T..(ID) as the parameter for Query; Details are in the tutorial. Share this post Link to post
grantful 3 Posted August 12, 2023 8 minutes ago, Stano said: You're going down a very bad road. ItemIndex has no meaningful value. I don't know TCustomListBox at all. I assume it has Items, which is a child of TString. It does the following: Name: string; ID: T.. - some class from TObject into which you can put an integer. Items.AddObject(Name, ID); You use T..(ID) as the parameter for Query; Details are in the tutorial. do you have a link to a tutorial ? I need to figure this out Share this post Link to post
grantful 3 Posted August 12, 2023 (edited) i am trying with a listview but now luck. procedure TForm2.ListView2ItemClick(const Sender: TObject; const AItem: TListViewItem); begin FDQuery1.Active := True; while not FDQuery1.Eof do begin fdquery1.SQL.Clear; FDQuery1.SQL.Text := ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink'); if ListView2.ItemIndex >= 0 then begin FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail); FDQuery1.Open; FDQuery1.Next; end; TabControl1.ActiveTab := TabItem8; end; end; i get an error at detail [dcc64 Error] uMain.pas(470): E2003 Undeclared identifier: 'detail' Edited August 12, 2023 by grantful Share this post Link to post
Stano 143 Posted August 13, 2023 Help You got it all on... First just a basic fix Give here an example of how you fill listview2.Items. We can't move without it Kindly name all your components in a meaningful way!!! procedure TForm2.ListView2ItemClick(const Sender: TObject; const AItem: TListViewItem); begin //// It has nothing to do here!!! /// It's supposed to be where you create FDQuery1 /// A separate function. For all Query FDQuery1.SQL.Text := ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink'); /// Something like that FDQuery1.ParamByName('IDDRINK').AsInteger := TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value; try FDQuery1.Open while not FDQuery1.Eof do begin /// Tu niečo urobíš FDQuery1.Next; end; TabControl1.ActiveTab := TabItem8; finally FDQuery1.Close; end; end; Share this post Link to post
grantful 3 Posted August 13, 2023 Thanks for your help i will try it out Share this post Link to post
aehimself 399 Posted August 14, 2023 While it works, storing and using data in the UI is never a good idea. If one day you want to change the ListBox to something else you’ll have to rewrite the whole logic. I’d suggest parsing (deserializing) the JSON into your custom class, filling the ListBox and extracting the ID from there when needed. Share this post Link to post
Serge_G 87 Posted August 14, 2023 First question : Is this supposed to be a FMX or a VCL program ? If FMX you can write this app with "no code" (except itemclick to change from list to view and reverse) using Livebindings Here a french tuturial I wrote (2018) 1 Share this post Link to post
grantful 3 Posted August 14, 2023 Thanks for all the comments. I will look into the tutorial. Share this post Link to post
grantful 3 Posted August 15, 2023 18 hours ago, Serge_G said: First question : Is this supposed to be a FMX or a VCL program ? If FMX you can write this app with "no code" (except itemclick to change from list to view and reverse) using Livebindings Here a french tuturial I wrote (2018) @Serge_G Very informative tutorial. I learned alot from it. I have a question about binding multiple fields to the same memo. I need to bind all of the stringrediants1,2,3 ect to the same memo. Do you have any more tutorials that might help with this or is there a way to do it you have not made a tutorial ?? Thanks for the help i really appreciate it. Share this post Link to post
Serge_G 87 Posted August 15, 2023 Hi, First, all my tutorials are Here For your need, you can use CustomFormat property of the link (should something like %s+' '+dataset.stringrediants1.value+....) I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious. but I suggest you to treat the problem at the datasource and concatenate the fields in your query (advantage 1 - readonly field, advantage 2 - speed) Share this post Link to post
Stano 143 Posted August 15, 2023 I have never used LiveBindings. Nor will I do so. The main reason is that I have no control over it. It's also not very clear. Share this post Link to post
Serge_G 87 Posted August 15, 2023 1 minute ago, Stano said: The main reason is that I have no control over it. It's also not very clear. Well, you can write all LiveBindings at runtime also 😉. I agree Visual LiveBindings is not a perfect tool 😲 Share this post Link to post
Stano 143 Posted August 15, 2023 DBGrid notes. When I started, I had it on the form for 3 days. Never more. I recommend VirtualStringTree (VST) instead. It works perfectly and you can do everything you can think of there. Because of it I created: A class for VST. This one takes care of the VST data for me. I have two duties. Create the SQL and handle the VST events Custom (DB)Navigator. So I'm relieved of bulk re-writing code. Share this post Link to post
Serge_G 87 Posted August 15, 2023 (edited) Hum, now I am looking the table structure IMHO the database structure is not a valid one. I think about a : Beverage table, Ingredient table, and Composition table instead of the "monolithic" table you seem to use (according livebinding screenshot Edited August 15, 2023 by Serge_G Share this post Link to post
grantful 3 Posted August 15, 2023 (edited) 2 hours ago, Serge_G said: Hi, First, all my tutorials are Here For your need, you can use CustomFormat property of the link (should something like %s+' '+dataset.stringrediants1.value+....) I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious. but I suggest you to treat the problem at the datasource and concatenate the fields in your query (advantage 1 - readonly field, advantage 2 - speed) Thanks for all your help and your tutorails. I was trying to use the query for the listview. FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail); this is where i was trying to fix the problem. Im sure some years back i did something like this and this line worked FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail); but now i am getting problems with this error [dcc64 Error] uMain.pas(627): E2003 Undeclared identifier: 'detail' I am looking into useing the live bindings https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_Custom_Format_and_Parse_Expressions_in_LiveBindings#Binding_Expressions I would like to figure out this problem with my code. Thanks for any help and any help with the query code. Edited August 15, 2023 by grantful Share this post Link to post
Stano 143 Posted August 15, 2023 57 minutes ago, grantful said: Im sure some years back i did something like this and this line worked That could never work. You're remembering wrong. One more time: TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value; Share this post Link to post
grantful 3 Posted August 15, 2023 13 hours ago, Stano said: That could never work. You're remembering wrong. One more time: TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value; @Stano Thanks for your patience. I have not worked with objects before. I took your advice and renamed some things. type TMyObject = class(TObject); procedure TForm2.lvDrinksListviewItemClick(const Sender: TObject; const AItem: TListViewItem); var idDrink: TMyObject; begin idDrink := TMyObject.Create; /// / It has nothing to do here!!! /// It's supposed to be where you create FDQuery1 /// A separate function. For all Query FDQuery1.SQL.Text := ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink'); /// Something like that FDQuery1.ParamByName('IDDRINK').AsInteger := idDrink(lvDrinksListview.Items.Objects[lvDrinksListview.ItemIndex]).Value; try FDQuery1.Open while not FDQuery1.Eof do begin /// Tu niečo urobíš FDQuery1.Next; end; TabControl1.ActiveTab := TabItem8; finally FDQuery1.Close; end; [dcc64 Error] uMain.pas(517): E2003 Undeclared identifier: 'Objects' [dcc64 Error] uMain.pas(517): E2003 Undeclared identifier: 'Value' I am using Delphi 11 community edition. This is and FMX multi device program. Can you perhaps tell me what i am doing wrong ? Thanks again for all the help. Share this post Link to post
Serge_G 87 Posted August 16, 2023 (edited) For me, you complicate your life 21 hours ago, grantful said: I was trying to use the query for the listview. If you use livebindings and synchronize your datasource to the listview you don't have to add a query. 23 hours ago, Serge_G said: I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious. I made some tests. Not so evident, I think the best way is to create a new method for livebindings (I explore this in this tutorial). For now, I just use a database (Firebird one) trick to get linebreak value and use CustomFormat:=%s+dataset.BR.text+dataset.stringrediants1.value+dataset.BR.text+dataset.stringrediants2.value+ ... Can you attach your database and I will write a quick program as demo ? Attached a quick sample Ok, I don't create UI to add some coktails, just respond to first question "show only the records based on the item i click in a listbox." (listview) Cocktails.zip Edited August 16, 2023 by Serge_G Demo added Share this post Link to post
grantful 3 Posted August 16, 2023 4 hours ago, Serge_G said: For me, you complicate your life If you use livebindings and synchronize your datasource to the listview you don't have to add a query. I made some tests. Not so evident, I think the best way is to create a new method for livebindings (I explore this in this tutorial). For now, I just use a database (Firebird one) trick to get linebreak value and use CustomFormat:=%s+dataset.BR.text+dataset.stringrediants1.value+dataset.BR.text+dataset.stringrediants2.value+ ... Can you attach your database and I will write a quick program as demo ? Attached a quick sample Ok, I don't create UI to add some coktails, just respond to first question "show only the records based on the item i click in a listbox." (listview) Cocktails.zip Thanks so much I will look at this and the tutorial. I had made it this far. var DrinkID: Integer; begin FDQuery1.SQL.Text := ('Select * From drinks Where idDrink = :_idDrink'); // showMessage (intToStr(fdquery1.FieldByName('idDrink').AsInteger)); FDQuery1.ParamByName('_idDrink').AsString := (TListViewItem(lvDrinksListview.Items.Item [lvDrinksListview.ItemIndex]).Text); // // strToInt(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text) ; FDQuery1.Open; momoDrinkIngrediants.Lines.Add(FDQuery1.FieldByName('strIngredient1') .AsString); momoDrinkIngrediants.Lines.Add(FDQuery1.FieldByName('strIngredient2') .AsString); FDQuery1.Next; TabControl1.ActiveTab := tiDrinksIngreediantsAndDirections; FDQuery1.Close; end; // ShowMessage(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text); // ShowMessage(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Detail); Share this post Link to post
Stano 143 Posted August 16, 2023 (edited) I've written once before that everything associated w/in DB should be capitalized. And name of component!!! * is only used in special cases. You always have to enumerate the required fields. FQryDrink.SQL.Text := 'SELECT * FROM DRINKS WHERE IDDRINK = :IDDRINK'; Why are you mixing Integer and string types? ItemIndex is not what you need. FDQuery1.ParamByName('IDDRINK').AsInteger := (TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text); I have never worked TListView in my life. So I looked at the TListItem properties It doesn't seem to me that it's something thrown in for you. It's too complicated. I assume you only need to display simple texes. Then I see two components suitable for you: ComboBox - only one item is visible VirtualStringTree (my favorite) - if you want to see all items Decide and let me know. Because your style will get us nowhere!!! Edited August 16, 2023 by Stano Share this post Link to post
Stano 143 Posted August 16, 2023 I went through the discussion again. I don't understand what you actually want to do. The description of the task is incomprehensible to me. Is it supposed to be a Master-Detail relationship? Are you working with one table or two? Can you put a snapshot of the form in question here? I'm sure that would help a lot. Why do you want to go into live bindings? Why do you need this? Share this post Link to post
grantful 3 Posted August 16, 2023 Thanks for your help Stano it is 1 table(drinks) there are fields stringrediants1 stringrediants2 stringrediants3. Etc So when I click on the listview item I need to get the. Field. ‘IdDrink’ from the table and load up all the stringrediants1,stringrediants2,stringrediants3 etc. from the same table into a Listview or listbox,or memo Thanks for your patience and help Share this post Link to post
Stano 143 Posted August 16, 2023 (edited) Hm, does that mean IDDRINK is repeated in the table? What are you going to do with that list? Its purpose. No translator will translate the field name, the rediant part Out of curiosity: which DB is it? Edited August 16, 2023 by Stano Share this post Link to post
grantful 3 Posted August 16, 2023 (edited) It is a SQLite database Example Table (Drinks) Fields idDrink,strDirections,stringrediants1,stringrediants2,stringrediants3,stringrediants4,etc so when I click on any record in the listview I need to use the idDrink (integer) and display all the fields idDrink field is int strdrink is string stringrediants1,stringrediants2,stringrediants3 is string so the strDirections will go into a memo the stringrediants3,2,3 etc will go in a memo Edited August 16, 2023 by grantful A Share this post Link to post