TcxGrid如何获取修改后的值并更新下一列的值?

时间:2018-10-09 04:03:25

标签: delphi tcxgrid

我正在使用XE2。当用户在网格中编辑单价时,我想做的是,自动重新计算总价格,这是下一个列。

我应该使用哪个事件?

我尝试了TCXGridTableView OnEditValueChanged,但无法获取修改后的值吗? AItem.EditValue是修改值之前的值。

然后我尝试了TcxGridColumn OnEditValueChanged。我可以这样获得修改后的值:

  cxCE := Sender as TcxCurrencyEdit;
  cxCE.Value; // this is the modified value

但是,如果用户修改了一个值,然后没有按Enter键,而是按TAB键离开,则出现了一个有趣的问题,这是一个问题:

  1. TcxGridColumn OnEditValueChanged事件确实执行。
  2. 我仍然可以获取cxCE.Value(修改后的值)并成功更新下一列的值。
  3. 仅在修改了下一列的值之后,cxCE.Value才恢复为修改值之前的值!
  4. 结果,用户输入被回滚,但是下一列确实更新了。

发生的例子:

数量|单价|总价

2 ...... 5 ....... 10

当用户将单价从5修改为7时,按Tab键 在OnEditValueChanged之后,单价回滚,但是我的逻辑更新了总价:

2 ...... 5(回滚)14(更新)

感谢任何人都可以帮助我,非常感谢。

1 个答案:

答案 0 :(得分:1)

  

我应该使用哪个事件?

以上都不是。我认为您正在以错误的方式进行操作。您似乎想要的是 当“数量”或“单价”字段更改时,将自动更新TotalPrice字段。 认为这是最有效的方法,它是一种数据处理操作, 而不是GUI操作,这就是您应该对其进行编码的方式。

cxGrid是一个可识别db的组件,它们被编码为自动 反映数据的更改,因此更新TotalPrice的方法 字段是通过对数据集进行操作的代码来完成的,而 在cxGrid上运行。如果您尝试在cxGrid的代码中执行此操作, 您会发现自己不断与网格“打架”,因为它知道 如何了解数据库,实际上您正在尝试颠覆这一点。

尝试下面的示例项目。设置一个新的VCL项目,添加一个TClientDataSet, TDataSource和TDBNavigator并以常规方式“连接”它们。

为CDS和FormCreate设置OnCalcFields事件处理程序 表单的事件,然后添加代码 如下所示。

项目运行时,它会动态创建一个cxGRid来显示数据(我做到了 之所以这样,是因为cxGrid中有太多设置和子组件, 最简单的方法是在代码中创建一个,而不是在这样的答案中指定其设置。)

尝试更改“数量”和“单价”字段中的值,然后 请注意,TotalPrice将自动更新,而无需任何代码 在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;