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 и нажал вкладку после OnEditValueChanged, цена за единицу откатилась, но моя логика обновила Итоговую цену:

2 ...... 5 (откат) 14 (обновлено)

Был бы признателен, если бы кто-нибудь мог мне помочь, большое спасибо.


person Eric Cheng    schedule 09.10.2018    source источник
comment
Скорее используйте базу знаний DevEx. (devexpress.com/Support/Center/Question/Details / T564409 /)   -  person nolaspeaker    schedule 09.10.2018
comment
ваше представление связано с набором данных или нет? если это так, просто измените набор данных   -  person Ago    schedule 12.10.2018


Ответы (1)


Какое событие мне следует использовать?

Ни один из вышеперечисленных. Я думаю, вы ошибаетесь. Кажется, вы хотите автоматически обновлять поле TotalPrice при изменении поля Qty или UnitPrice. Самый продуктивный способ думать об этом - как об операции манипулирования данными, а не как об операции с графическим интерфейсом пользователя, и именно так вы должны ее кодировать.

CxGrid - это компонент, поддерживающий базу данных, и они закодированы для автоматического отражения изменений данных, поэтому способ обновления поля TotalPrice - это сделать это в коде, который работает с набором данных, НЕ в коде, который работает с cxGrid. Если вы попытаетесь сделать это в коде для cxGrid, вы обнаружите, что постоянно «боретесь» с сеткой, потому что она знает, как быть осведомленной о БД, и вы, по сути, пытаетесь это разрушить.

Попробуйте приведенный ниже пример проекта. Настройте новый проект VCL, добавьте TClientDataSet, TDataSource и TDBNavigator и «подключите их» обычным способом.

Настройте обработчик событий OnCalcFields для CDS и событие FormCreate для формы, а затем добавьте код, показанный ниже.

Когда проект запускается, он динамически создает cxGRid для отображения данных (я сделал это таким образом, потому что в cxGrid так много настроек и подкомпонентов, что проще всего создать их в коде, а не указывать его настройки в ответе вроде это).

Поиграйте с изменением значений в полях Qty и UnitPrice и обратите внимание, что 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;
person MartynA    schedule 09.10.2018
comment
Это помогло или вы все еще застряли? - person MartynA; 12.10.2018