TDBLookupComboBox shows nothing - delphi

I am trying to list of my users table's username in combobox. I find a dblookupcombobox for this. But it does not show anything.
I set the datasource to my dsUser and datafield to username. But it does not show anything. Also i open ADQueryUser.Open in formcreate.
If i use TDBCombobox, this time it shows only first row and i cannot search or etc.
I checked the my TFDQuery which is work. I can see my data in DBGrid.
Also i tried to refresh it:
procedure TFormMain.FormShow(Sender: TObject);
begin
ADQueryUser.Open;
DBLookupComboBox1.Refresh;
end;
I want to use combobox to search and select using keyup any selecting option. But which combobox is fitting my requirements ? And how can i use ?

DataSource and DataField are the datasource and field you would be modifying using the control. Similar to the DataSource and DataField properties of a plain TDBEdit, they only declare where the value of your control is stored in, not what is listed.
Use ListSource, ListField and KeyField to define the datasource, visible values (e.g. user name) and keyfield (e.g. userid) that is used to populate the list.

Related

Delphi Firemonkey ComboBox insert in AdoTable

So, I've been using LiveBindings between two tables at a combobox to get the Id and Description of a foreign key(with the Item.LookupData and Item.text properties) and assign the key to a field in another table with the SelectedValue propertie. This is working fine i guess but i'm using custom dbnavigator controls to make a "register form".
I'm using methods like this to make the inserts: adotablealuno.FieldValues['Nome']:=editnomeAluno.Text;
But I'cant find how to use the combobox in this way, i've already tried the ItemIndex and Selected properties, but none of this work (I'm using a Access DB btw). How can I use my foreign key in ComboBox for this?
Actually I was already stating this question and there was no good answer for a long time. I found a way out that I am currently using. At least I know that I'll get reliable data.
You need to handle OnFillingListItem event of the LinkFillControlToField link in alike way and store id number in ComboBox Items. I use Tag property for this purpose though it is not actually good.
procedure TForm1.LinkFillControlToField1FillingListItem(Sender: TObject;
const AEditor: IBindListEditorItem);
begin
(AEditor.CurrentObject as TListBoxItem).Tag :=
YourLookuptable.FieldByName('id').AsInteger;
end;
And then fetch the item id from ListBox1.Selected.Tag. The text value can be accessed via ComboBox1.Selected.Text.
Appended.
You make an alike LinkFillControlToField link.
Then you select this link and create an OnFillingListItem event handler to the link (select events tab in the Object Inspector and double click on OnFillingListItem ComboBox). The event handler (empty procedure) will appear. It will be given a name like TForm1.LinkFillControlToField1FillingListItem(... Then you write the code setting the id property to the items' Tags.

Cannot assign to a read only property

I have a form which has a TDBLookupComboBox on it.
The TDBLookupComboBox is displaying a list of records from within a database table.
At the point of the forms OnShow event I would like the TDBLookupComboBox to already display one of the strings in the list.
I have done this so far...
procedure TfrmMain.FormShow(Sender: TObject);
begin
dblucbox.Text := Username;
end
Username is a string for one of the records already in the list.
At the point of compiling, I get an error saying
Cannot assign to a read only property
I'm a bit stuck with this so any help would be appreciated.
Don't try to modify the Text property, instead if you want set the TDbLookUpComboBox in a particular item you must use the the KeyValue property which will try to locate the record in the underlying TDataSet.
So you if you have Key Value of the user you can use something like this
dblucbox.KeyValue := UserId;
Otherwise you can use the Locate method of the underlying TDataSet, to find the match and the LookUp control will be refreshed automatically
You're going about this backwards. To be more precise, the DBLookupCombo is reflecting the state of the database table. So you want to be manipulating the table, not the combobox.
In other words, the OnShow event needs to open the table that's the object of the DBLookupCombo (if it's not already open) and then position the current record to be the one you want displayed as the default.

How to add a non-bound column to a DevExpress DB QuantumGrid

I am using these components:
UniDac for connection to mysql database
DevExpress for QuantumGrid
IDE:
Embarcadero Rad Studio XE2
I have a cxGrid component with one level and a cxGrid1DBTableView specified as the level's View. I can get data from my database and edit it in the grid. I want to add a column that is not in the bound DataSet. When I specify the Column properties value as CheckBox I can see the column but I can't change the value from unchecked to checked by clicking it. The field doesn't have a DataBinding assigned to it. I tried other types of Properties but all are the same I cant change the row value in the grid.
I've been searching for a way to fix this for couple of days, so im hoping you guys can help me.
Are you trying to add a checkbox item that does not have a database field behind it? I have this on one of my forms.
In addition to setting the Properties to "Checkbox" you need to set the DataBinding -> ValueType to "Boolean". The DataBinding->FieldName can be left blank.
To access the values or change their defaults you can use the DataController like this:
View.DataController.Values[i, CheckBoxFieldIndex] := true;
In addition you need to set
DataController.DataModeController.SmartRefresh := true;
To set that option you will also need a KeyField defined for the Controller (DataController.KeyFieldNames)
Setting the SmartRefresh to true will prevent the grid from trying to get an updated value from the underlying dataset. You need to prevent the refresh or the value for the non-bound column will be set back to Null. This comes with some restriction on how you update your dataset. Any changes made to the data in code will not be reflected by the grid unless you explicitly refresh the grid.
You also have to fill the field View.DataController.KeyFieldNames with one of the datasets fields. At least I need it in Delphi 7.

Dbgrid - automatic post to database

I have a form with a query, a dataset, an editable dbgrid and an updatesql component. When I need to save the changes made in the dbgrid, I call this procedure:
procedure TEditCardDetailForm.SaveChanges;
begin
Database1.StartTransaction;
try
Query2.ApplyUpdates;
Database1.Commit;
except
Database1.Rollback;
raise;
end;
Query2.CommitUpdates;
end;
However I want the changes to be applied automatically to the database when I press Enter or go to another row after editing a cell in the dbgrid - the way it is done when I use a TTable component. Is there a way to do it?
If I understand it right (please correct me if not) you have a TQuery with CachedUpdates set to true, but want it to behave as if it would not be using cached but immediate updates. If that is the case the way you have set up your TQuery contradicts your desired behaviour. Cached updates are to be "held" on the client side until you decide to manually post them to the database by using ApplyUpdates.
In case you can set CachedUpdates to false, you only need to do following:
Link the TUpdateSQL to the TQuery via its UpdateObject property.
Write the insert, update and delete statements and assign them to the InsertSQL, ModifySQL and DeleteSQL properties of the TUpdateSQL.
I guess you already have done these two things, so putting CachedUpdates to false should do it.
You can find more information on Cached Updates for Delphi 5 here.
HTH
You have two scenarios to handle here:
save changes when changing the grid row
save changes when changing the grid column
The first one is easy to implement by calling your SaveChanges procedure in the AfterPost event of the underlying dataset (query2, a TClientDataSet?).
For the second one you only have to call query2.Post after the column has changed. This can be done in the OnDataChange event of the datasource. Make sure to check for Field <> nil and the dataset being in insert or edit mode before calling post.

working with Delphi and Access

I want to write an app that uses a Access database (*.mdb). I know how to connect to a mdb and how to use SQL statements. My problem is that I want to put the result of a query into a TListView.
Any info/link/book is welcomed
:)
Pull your result and then pass it to the following procedure (for example):
Query.First;
While not Query.EOF do
begin
StrObj := tStringList.create;
StrObj.Add(Query.FieldByname('id').asString);
ListView.AddItem(Query.FieldByName('Title').AsString,StrObj);
Query.Next;
end;
This will load your list view with nodes named by the fieldname title, and each node will contain a tstringlist containing whatever data you want to store for each node. Personally I would extend this and use a custom holder object rather than the tStringList, but this was just an example.
TListView is not a data-aware component, and there isn't (AFAIK) a VCL TDBListView - if you need a grid of data, you can either bind to a TDBGrid, or use a 3rd part TDBListView, which you can find with a quick google.
Using a ListView to represent a disconnected set of data is my favorite design pattern with Delphi database applications. The ListView control offers several different display formats of which vsReport is the one that looks like a table of data with rows and columns (the others are vsList, vsIcon, and vsLargeIcon).
To create "items" (which map to rows, at least when vsReport is the display style) you call AddItem() on the ListView's Items collection. AddItem will return an object of type TListItem. You can assigne a Caption to the item which becomes the description (in vsList, vsIcon, and vsLargeIcon styles) and the first column of the "table" in vsReport. The list item also has a TStringList property called SubItems. Each string added to SubItems will provide data for another column in vsReport mode (the SubItems are ignored in the other modes).
Finally, if you want to associate an integer primary key value back to your original database record you can do this using the TListItem's Data member. This is a pointer to an object associated with the item, but you can cast an integer and store it away there.
So, for instance:
DS := TSomeKindOfDataSet.Create();
try
//Set up and open DS.
while not DS.eof do begin
with ListView.Items.Add() do begin
//establish three columns for vsReport display
Caption := DS.FieldByName('DescriptiveField').AsString;
SubItems.Add(DS.FieldByname('AnotherColumn').AsString);
SubItems.Add(DS.FieldByname('YetAnotherColumn').AsString);
//Save the record's PK value
Data := Pointer(DS.FieldByname('PKColumn').AsInteger);
end;
DS.Next;
end;
finally
DS.Free;
end;
This gives you a list view containing the data from DS, along with the primary key value so that you can locate any record the user selects in the list view. DS is closed and disposed of while the user is working with the list view, so there's no ongoing demand on the database.
You can either add each record to a TListView. Just looping through the records and put the contents of the fields into the required control.
But Delphi provides data aware controls. That take care of the database connection. For most applications this is enough.
There are some implementations of VirtualTreeView that work with databases.
Here's one link, and here is VirtualTreeView web site.

Resources