Azad Salahli
Azad Salahli

Reputation: 916

Modify DBGrid cell content before it is displayed

I want to modify the content of a particular cell in dbgrid control when the database is loaded. For example, lets say I don't want any field of database to be displayed in dbgrid if it is equal to "forbidden". Is there any way that I can do that?

Upvotes: 3

Views: 7694

Answers (6)

Eugene Kuzmenko
Eugene Kuzmenko

Reputation: 965

I think that the best way would be not to SELECT the fields WHERE SOME_VALUE="forbidden" FROM the DATABASE_TABLE

Upvotes: 1

No'am Newman
No'am Newman

Reputation: 6477

I would modify the query that provides the data to the grid so as not to include rows (tuples) which have the 'forbidden' string. This seems much easier than trying hard not to display data after it has already been retrieved from the database.

Upvotes: 2

APZ28
APZ28

Reputation: 1007

Hookup OnAfterOpen event on dataset. Get the hidden fields and set its Visible property to False and your dbgrid will not display them

Cheers

Upvotes: 2

jachguate
jachguate

Reputation: 17203

Going to your original question:

Use the OnGetText event of the field to provide a different value from what is stored on the database for presentation purposes.

The DisplayText boolean parameter will be True if the value is required to be presented to the user and will be False if the value is required for other purposes.

procedure TForm1.SQLQuery1Field1GetText(Sender: TField; 
  var Text: string; DisplayText: Boolean);
begin
  if (Sender.AsString = 'forbidden') and (DisplayText) 
    and (PrivilegeLevel(CurrentUser) < 10) then
    Text := '********'
  else
    Text := Sender.AsString;
end;

Upvotes: 5

jachguate
jachguate

Reputation: 17203

Using the DataSet events to synchronize UI is not a good practice. You can rely on DataSource events to do that, separating UI Logic from business logic.

As the state of the DataSet will change from dsInactive to dsBrowse, you can rely on the DataSource OnState change to make anything UI-related upon the data is loaded from database.

You can rely on a Auxiliar field to track previous state to avoid the code executing more than needed.

for example (untested code)

procedure TForm1.DataSource1StateChange(Sender: TObject);
begin
  if (DataSource1.State = dsBrowse) and (not FUIStateInSync) then
  begin
    //dataset is open, change UI accordingly
    DBGrid1.Columns[0].Visible := SomeCondition();
    //this will prevent the code to be executed again 
    //as state comes to dsBrowse after posting changes, etc. 
    FUIStateInSync := True; 
  end
  else if (DataSource1.State = dsInactive) then
    FUIStateInSync := False; //to let it happen again when opened.
end;

I publish this even when you have an accepted answer, because O.D. suggestion is just what you shall avoid.

Upvotes: 3

CloudyMarble
CloudyMarble

Reputation: 37576

you can use the DataSetNotifyEvent Afteropen

DBGrid.Datasource.Dataset.Afteropen :=

and you can hide fields with:

if Condition then DBGrid.columns[x].visible := false

alternative you can check the condition on the OnDrawColumnCell event in order to overrite / delete some content in a specific cell

Upvotes: 3

Related Questions