Which event I should use?
None of the above. I think you are going about this the wrong way. What you seem to want is to
automatically update the TotalPrice field when the Qty or UnitPrice field changes.
The most productive way to think of that is as a data-manipulation operation,
rather that a GUI operation,and that's the way you should code it.
The cxGrid is a db-aware component, and these are coded to automatically
reflect changes to the data, so the way to go about updating the TotalPrice
field is to do it in code which operates on the dataset, NOT in code
which operates on the cxGrid. If you try to do it in code for the cxGrid,
you'll find yourself continually "fighting" with the grid, because it knows
how to be db-aware and you're trying, in effect, to subvert that.
Try the example project below. Set up a new VCL project, add a TClientDataSet,
TDataSource and TDBNavigator and "wire them up" in the usual way.
Set up an OnCalcFields event handler for the CDS and an FormCreate
event for the form and then add the code
shown below.
When the project runs, it dynamically creates a cxGRid to display the data (I did it
this way because there are so many settings and sub-components in a cxGrid that
it's easiest to create one in code rather than specify its settings in an answer like this).
Play about with changing the values in the Qty and UnitPrice fields and
notice that the TotalPrice automatically updates without requing any code
which operates on the cxGrid.
type
TForm1 = class(TForm)
CDS1: TClientDataSet;
DS1: TDataSource;
DBNavigator1: TDBNavigator;
procedure FormCreate(Sender: TObject);
procedure CDS1CalcFields(DataSet: TDataSet);
private
public
cxGrid : TcxGrid;
cxLevel : TcxGridLevel;
cxView : TcxGridDBTableView;
end;
[...]
// This is a utility function to create TFields in code
function CreateField(AFieldClass : TFieldClass; AOwner : TComponent; ADataSet : TDataSet;
AFieldName, AName : String; ASize : Integer; AFieldKind : TFieldKind) : TField;
begin
Result := AFieldClass.Create(AOwner);
Result.FieldKind := AFieldKind;
Result.FieldName := AFieldName;
Result.Name := AName;
Result.Size := ASize;
Result.DataSet := ADataSet;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
Field : TField;
Col : TcxGridDBColumn;
begin
// First, create the Fields of the ClientDataSet
Field := CreateField(TIntegerField, Self, CDS1, 'ID', 'CDS1ID', 0, fkData);
Field := CreateField(TIntegerField, Self, CDS1, 'Qty', 'CDS1Qty', 0, fkData);
Field := CreateField(TCurrencyField, Self, CDS1, 'UnitPrice', 'CDS1UnitPrice', 0, fkData);
Field := CreateField(TCurrencyField, Self, CDS1, 'TotalPrice', 'CDS1TotalPrice', 0, fkInternalCalc);
// Field.ReadOnly := True;
CDS1.CreateDataSet;
CDS1.IndexFieldNames := 'ID';
// Next, populate the CDS with a few records
// Note : If we are using calculated fields, we do to need to specify
// a value for the TotalPriced field
CDS1.InsertRecord([1, 1, 1]);
CDS1.InsertRecord([2, 2, 5]);
CDS1.InsertRecord([3, 3, 6]);
CDS1.First;
// Now, create a cxGrid to display the CDS data
cxGrid := TcxGrid.Create(Self);
cxGrid.Parent := Self;
cxGrid.Width := 400;
cxLevel := cxGrid.Levels.Add;
cxLevel.Name := 'Firstlevel';
cxView := cxGrid.CreateView(TcxGridDBTableView) as TcxGridDBTableView;
cxView.Name := 'ATableView';
cxView.DataController.KeyFieldNames := 'ID';
cxView.DataController.Options := cxView.DataController.Options + [dcoImmediatePost];
cxLevel.GridView := cxView;
cxView.DataController.DataSource := DS1;
cxView.DataController.CreateAllItems;
// Since the TotalPrice column is a calculated field, we need to
// prevent the user from attempting to edit it
Col := cxView.GetColumnByFieldName('TotalPrice');
Col.Options.Editing := False;
ActiveControl := cxGrid;
end;
// Procedure to calculate the TotalPrice field
procedure CalculateTotalPrice(DataSet : TDataSet);
var
Qty : Integer;
UnitPrice,
TotalPrice : Currency;
begin
Qty := DataSet.FieldByName('Qty').AsInteger;
UnitPrice := DataSet.FieldByName('UnitPrice').AsCurrency;
TotalPrice := Qty * UnitPrice;
DataSet.FieldByName('TotalPrice').AsCurrency := TotalPrice;
end;
procedure TForm1.CDS1CalcFields(DataSet: TDataSet);
begin
CalculateTotalPrice(DataSet);
end;