How to access data record after ListBox selected with LiveBindings - delphi

I have a TSQLDataset, Im using the livebindings to bind it to a listbox. When I click on the listbox item, I want to be able to access the other fields of data from the record, but I cannot figure out how to do it because I cannot get the dataset to the corresponding item.
I know that I could possibly take the ID Field and maybe assign it to Selected.Tag using live bindings but can't figure that out either, but if I could then I could have another a SQLQuery and then just return the result of the query
SELECT * FROM Dataset WHERE ID=(Tag value)
That would work, but I don't know how to get livebindings to set the items tag value when live bindings populates the Listbox.
Does anyone know how to make this work?

It is easier to link Tag property of the ListBox with the ID of the record.

There's a Sensor Info demo application from Embarcadero in XE5 Samples directory...
There you have OnItemClick = lbMainItemClick in TListBox events then you have to define the event handler:
procedure TfrmAboutSensors.lbMainItemClick(const Sender: TCustomListBox; const Item: TListBoxItem);
begin
if Assigned(Item.OnClick) then
Item.OnClick(Item);
end;
And then for every item on the list:
for LItem in LListBox do
begin
//LItem.ItemData.Accessory := TListBoxItemData.TAccessory.aDetail; // my code
//LItem.ItemData.Accessory := TListBoxItemData.TAccessory.aNone; // my code
LItem.OnClick := ListBoxItemClick;
end;
Please give us callback if that helps.

Related

Listbox does not show the changes made to the Dataset

I have a FMX ComboBox connected through LiveBindings to a ClientDataset. Everything works fine, until I needed to filter the data from the ClientDataset. After applying the filter, ComboBox.Items and ComboBox.ListItems are ok, i.e., it is the data contained in the filtered ClientDataset. But the data that the ComboBox listbox shows is always the same: the data that the ClientDataset contained the first time the listbox was displayed.
procedure TForm14.Button1Click(Sender: TObject);
begin
LinkFillControlToField1.Active := False;
ClientDataset1.Filter := 'TYPE = ''N''';
Clientdataset1.Filtered := not ClientDataset1.Filtered;
// Deactivate and Reactivate the link is necessary to refresh the data
LinkFillControlToField1.Active := True;
end;
In that code I change the filter to the ClientDataset and I deactivate the LinkFillControlToField and after applying the filter I activate it again to refresh the data. It works without problems with TListBox and other controls, but not with a TComboBox, although ComboBox.Items and ComboBox.ListItems do contain the correct data, but it is not the one shown in the combobox listbox.
Is there a way to solve this, using LiveBindings ? I have looked for properties and methods of the ComboBox (Repaint for example), the LinkFillControlToField and the BindSourceDB, but nothing has worked for me.
I use Delphi 10.4 Update 2, Firemonkey Windows application (32 or 64) running on Windows 10.
TIA.,
Ricardo
I had the same problem. My data source was TFireDAC TQuery. I submitted a change to a parma contained in the query.
My solution to my problem was to insert the line to explicitly clear the list of items.
if (SCM != NULL && SCM->qrySession->Active) {
SCM->qrySession->DisableControls();
// remove all the strings held in the combobox
// note cmbSessionList->Clear() doesn't work here.
cmbSessionList->Items->Clear();
SCM->qrySession->Close();
// ASSIGN PARAM to display or hide CLOSED sessions
SCM->qrySession->ParamByName("HIDECLOSED")->AsBoolean = fHideClosedSessions;
SCM->qrySession->Prepare();
SCM->qrySession->Open();
SCM->qrySession->EnableControls();
}

How to get the values of TListView selected item in Firemonkey Delphi Rio

I have a TListView populated with data from TFDQuery using Livebindings.
I would like to get the values of the selected item like the item.text, itemheader.text, etc. I already figured out the selected item through listview1.itemindex but to get the values is a struggle to me. I am new with TListView and livebindings. I've spent over a day already looking for answers in the internet but looks too complicated for a very simple task. I know there is a straight method for this.
Anyone care to share some clues (codes) on how to get the values of listview selected item?
MORE DETAILS:
I am using the Livebindings dynamic appearance. I created items for my query fields and map them accordingly to my TListView.
It so happen that I did not use the default item.text but instead map fields to my created items like item.text1, item.text2, item.item3.
Hence, this is the reason why I am not getting the caption from the formula given by MartynA below.
Perhaps I am missing your point (in which case I'll delete this) but the following FMXcode works fine for me:
procedure TForm1.Button2Click(Sender: TObject);
var
Index : Integer;
begin
Index := ListView1.ItemIndex;
if Index >= 0 then
Caption := ListView1.Items[Index].Text;
// OR ShowMessage(ListView1.Items[Index].Text);
// OR Label1.Text := ListView1.Items[Index].Text;
end;

What has happened to ComboBox.Sorted := True; in Delphi 10.2?

Having recently received a 'Tumbleweed' badge for my last question, I am not sure whether I should be asking any more questions, but here goes.
I am populating a TComboBox with items from a sqlite table and this works fine. In my previous version of Delphi I was able to use ComboBox1.Sorted := True; to sort the items, but this seems to have disappeared in Delphi 10.2. I can sort the items in the table by applying a query and then populate the TComboBox from the sorted table. However, for curiosities sake I would like to find out how one now sorts items in a TComboBox. I have found some references to TComboBox(Sort:Compare) but have not succeeded in getting this to work to as of yet.
Can somebody please shed some light on this - many thanks
In Firemonkey you can populate a TComboBox instance either simply with the Items property of type TStrings or you add TListBoxItem instances with the form designer. But internally always TListBoxItem for the elements is used.
To use the TComboBox.Sort you need to provide an anonymous compare-function.
This is a simple example usage of TComboBox.Sort
cbxItems.Sort(
function (pLeft, pRight: TFMXObject): Integer
var
lLeft, lRight: TListBoxItem;
begin
lLeft := TListBoxItem(pLeft);
lRight := TListBoxItem(pRight);
Result := String.Compare(lLeft.Text, lRight.Text);
end
);

How can I obtain the dataset row for the selected item of FMX.ListView.TListView?

My question relates to the use of Firemonkey TListView in Delphi 10.2 Tokyo.
I have a FMX form with a ListView with ItemAppearance.ItemApearance = which allows me to add any number of TTextObjectAppearance items.
The TListView has LiveBindings to TFDQuery fields via a TBindSourceDB. All my fields display as I want them to in the ListView.
I do not wish to display the primary key from that query to the user but I do want to be able to receive the primary key once the user selects an item in the listview.
The goal is to be able to locate the row in the TFDQuery dataset that contains other columns of information required to generate the next screen.
I would much appreciate your advice. Thanks in advance.
A solution for TListView based on asd-tm's comment worked for me.
For the original post see see this.
procedure TForm1.LinkFillControlToFieldPKFillingListItem(Sender:
TObject; const AEditor: IBindListEditorItem);
begin
(AEditor.CurrentObject as TListItem).Tag := FDQuery1.FieldByName('PK').AsInteger;
end;
procedure TForm1.ListView1ItemClick(const Sender: TObject; const
AItem: TListViewItem);
begin
FDQuery1.IndexFieldNames := 'PK';
FDQuery1.SetKey;
FDQuery1.FieldByName('PK').AsInteger := AItem.Tag;
if FDQuery1.GotoKey then
//...
end;

Tlistview - There is any component like Tlistview but with DB access?

I've been trying to make a creative thing to avoid the dbgrids, and i've found the Tlistview (using the one from alphaskins, tslistview), and seems to be a nice way!
The problem is, I don't want to code the event onclick on every tlistview to position a record/dataset according to the item I selected on the tlistview .. and I'm doing it with the tlistview item's caption.. and there could be records with the same names
Here is one of the codes I want to avoid:
with q_find_process do
begin
close;
sql.Clear;
sql.Add('Select * from t_process where process_name like '+quotedstr(streeview1.Selected.Text)+');
open;
end;
And no, I don't want to put the ID of the Record on the item caption..!
Any ideas?
Does anyone know other way of showing a lot of records without being only text text and more text? I don't know all components on the tool palette, maybe someone could suggest me other one..
I have sometimes used listviews which have been loaded from database tables - only for small amounts of data. I don't understand what you mean by I don't want to code the event onclick on every tlistview to position a record/dataset according to the item I selected on the tlistview, so I'm going to show you how I solved this problem.
Basically, I create a sub-item which holds the primary key of each record. All the user interface code uses two list views, and at the end, the database is updated. There is no interaction with the database between loading and storing (which might be where I avoid your 'onclick' problem). The widths of each fields are set in the Object Inspector; the final subitem's width is 0 (ie not displayed).
Loading the list view:
srclist.items.clear;
with qSrcList do
begin
close;
params[0].asdate:= dt; // use date of deposit
open;
while not eof do
begin
ListItem:= srclist.Items.Add;
ListItem.Caption:= fieldbyname ('kabnum').asstring;
ListItem.SubItems.Add (fieldbyname ('price').asstring);
ListItem.SubItems.Add (fieldbyname ('duedate').asstring);
ListItem.SubItems.Add (fieldbyname ('docket').asstring);
ListItem.SubItems.Add (fieldbyname ('id').asstring);
next
end;
close
end;
Saving data:
with dstlist do
for index:= 1 to items.count do
with qInsert do
begin
dstlist.itemindex:= index - 1;
lvitem:= dstlist.selected;
parambyname ('p1').asinteger:= deposit;
parambyname ('p2').asinteger:= strtoint (lvitem.SubItems[3]);
parambyname ('p3').asfloat:= strtofloat (lvitem.SubItems[0]);
execsql;
end;
I hope that this helps you. The context of this code (not that it matters too much) is in a financial application where the user wishes to populate a bank deposit form with cheques. SrcList holds the cheques which have yet to be deposited (there will only be a few per given date) and DstList holds the cheques which have already been connected to a given deposit form.

Resources