I have a database populating a TDBGrid in Delphi 2007 Pro. When the grid finishes populating, I want to automatically fill a list box based on data processed from the grid. I can do this manually by watching and waiting for the grid to completely fill with the dataset and then calling my next procedure. Is there an event that would allow calling the next procedure when the grid finishes populating automatically? Thanks.
views:
77answers:
2
+2
A:
If you're using a TDataSet
descendant, you can use its AfterOpen
event:
"AfterOpen is called after the dataset establishes access to its data and the dataset is put into dsBrowse state."
edit (code sample for comments for Duilio's answer): In the below, 'CDS' is a 'TClientDataSet'. A 'TDBGrid' is also attached to the data set by means of a 'TDataSource', but the grid's functionality is not in any way effected by the code below, or the ListBox's functionality with the grid's for that matter..
procedure TForm1.CDSAfterOpen(DataSet: TDataSet);
var
sl: TStringList;
begin
sl := TStringList.Create;
try
sl.Sorted := True;
sl.Duplicates := dupIgnore;
DataSet.DisableControls;
try
DataSet.First;
while not DataSet.Eof do begin
sl.Add(DataSet.Fields[1].AsString);
DataSet.Next;
end;
DataSet.First;
finally
DataSet.EnableControls;
end;
ListBox1.Items.Assign(sl);
finally
sl.Free;
end;
end;
Sertac Akyuz
2010-10-07 22:54:16
Correct, the DBGrid is a "window." I suspected I might have to work at the TDataSet level. AfterOpen triggers seconds before the TDBGrid is populated so it spawns an error. A TDBListBox is a great idea. What I do when the TDBGrid is finished filling all its rows from the database, I sort one of the fields in a string list: sl := TStringList.Create; sl.Sorted := True; sl.Duplicates := dupIgnore; and put that into an ordinary list box. I am not sure how I would do that with a TDBListBox. Thanks for the suggestions, I will try some things.
SteveJG
2010-10-08 22:27:14
@Steve - 'AfterOpen' is *really* triggered when the DatSet's opening is complete. Make sure it's the DataSet linked to the DataSource of the Grid... Regarding a 'TDBListBox', unlike a DBGrid, it is not a control to be populated with data from multiple records. See its [documentation](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/12ctrlsusingtdblistboxandtdbcombobox_xml.html).
Sertac Akyuz
2010-10-09 15:05:41
Sertac, thank you. This code example does exactly what I need. The DBListBox populates correctly even before the DBGrid is finished populating, It still seems there is no way to know (other than by inspection), when the DBGrid finishes populating. Great work.
SteveJG
2010-10-20 21:16:08
A:
I think you could execute:
TDataSet.Open;
TDataSet.FetchAll;
{At this point DBGrid should be populated}
This will get all the data from your table. When done, your DBGrid should be populated.
Duilio Juan Isola
2010-10-09 23:51:40
That might work to populate the grid. At the moment the dataset has about 6000 records, and requires about one second from opening to fill the DBGrid. I have no trouble filling the grid; what does not seem possible is to determine when the grid is populated and then execute another function upon completion, that is, execute the function as soon as the grid "knows" it is filled with the dataset. The DBGrid does not seem to have an event WhenFinishedPopulating from a dataset. Thank you for your idea, it just does not solve the problem.
SteveJG
2010-10-11 13:05:01
@Steve - If you're not doing any `ProcessMessages` while retrieving your data, you might try posting a message to your form, like in [this answer](http://stackoverflow.com/questions/382527/delphi-app-initialization-best-practices-approach/382860#382860). You might also try deriving a 'TDBGrid' descendant and override its `LayoutChanged` together utilizing a global flag perhaps. *But* why/how is your code depend on the status of the grid?, how does the grid *process* data? If you need records they're in the dataset...
Sertac Akyuz
2010-10-12 14:09:12
I temporarily solved the problem using a timer. Not ideal, but it does load the function I want loaded "automatically." The function I execute depends on the grid being fully populated..it can not work with incomplete data. The grid does NOT process any data, the function does. If I "need records they're in the data set" is true..I can easily copy all the field data I need into a DBListBox..I get a complete list, however, I do not want a complete list..I need a list with duplicates removed and "alphabetized."
SteveJG
2010-10-14 22:00:22
My function takes the field of interest, loads it into a TStringList where I sort it and remove duplicates. I tried writing the function into the DBListBox events but could not get it to work, so for the moment, using a timer gets the job done; however it does not answer the original question...I assume it is not possible to do what I want to do with a standard DBGrid without writing my own control or accessing an application event handler.
SteveJG
2010-10-14 22:01:20