Table of Contents

Inplace editor events

Intercept value transfer, customize editor creation, validate close/exit, and use keyboard lookup when editing is disabled.

Overview

The basic Editing cells guide covers enabling editors and choosing editor types. This chapter focuses on the event points around the editor lifecycle.

Stage Events
Open editor OnBeforeOpenInplaceEditor, OnAfterOpenInplaceEditor
Load value into editor OnBeforeInplaceEditorGetValue, OnAfterInplaceEditorGetValue
Write value back OnBeforeInplaceEditorSetValue, OnAfterInplaceEditorSetValue
Close editor OnBeforeCloseInplaceEditor, OnAfterCloseInplaceEditor
Grid focus leaves OnBeforeExitInplaceEditor, OnAfterExitInplaceEditor
Keyboard lookup Options.Lookup, OnBeforeLookup, OnAfterLookup

Open and close

Prevent editing for specific cells in OnBeforeOpenInplaceEditor:

procedure TForm1.GridBeforeOpenInplaceEditor(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  var AValue: TTMSFNCDataGridCellValue; var ACanOpen: Boolean);
begin
  if ACell.Column = ReadOnlyColumn then
    ACanOpen := False;
end;

Validate before the editor closes:

procedure TForm1.GridBeforeCloseInplaceEditor(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  ACancelled: Boolean;
  var AValue: TTMSFNCDataGridCellValue;
  var ACanClose: Boolean);
begin
  if not ACancelled and AValue.IsEmpty then
  begin
    ShowMessage('Value is required.');
    ACanClose := False;
  end;
end;

Use exit events when focus leaves the grid entirely. Use close events when an edit session ends while the grid remains active.

Value transfer

Use the "before" value events to override the default transfer.

procedure TForm1.GridBeforeInplaceEditorGetValue(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  var AValue: TTMSFNCDataGridCellValue; var AHandled: Boolean);
begin
  if ACell.Column = AmountColumn then
  begin
    AValue.AsString := FormatFloat('0.00', AValue.AsFloat);
    AHandled := True;
  end;
end;

Validate before writing back:

procedure TForm1.GridBeforeInplaceEditorSetValue(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  var AValue: TTMSFNCDataGridCellValue; var AHandled: Boolean);
begin
  if (ACell.Column = QuantityColumn) and (AValue.AsInteger < 0) then
  begin
    ShowMessage('Quantity cannot be negative.');
    AHandled := True;
  end;
end;

Data-level cell edit events

Three events operate at the data layer rather than the renderer layer. They receive TTMSFNCDataGridCellValue directly and fire independently of which editor type is active — including custom editors.

Event When it fires What you can do
OnCellEditGetData Just before the editor is loaded with the cell's current value. Replace the value the editor sees (e.g. reformat it).
OnCellEditSetData Just before the edited value is written back to the cell. Transform the value before it is stored (e.g. strip whitespace, apply units).
OnCellEditValidateData Before the edit is accepted; AValid defaults to True. Reject invalid input by setting AValid := False.
procedure TForm1.GridCellEditGetData(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  var AValue: TTMSFNCDataGridCellValue);
begin
  // Show stored temperature in °F; it is stored in °C
  if ACell.Column = TempColumn then
    AValue := TValue.From<Double>(AValue.AsExtended * 9 / 5 + 32);
end;

procedure TForm1.GridCellEditSetData(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  var AValue: TTMSFNCDataGridCellValue);
begin
  // Convert °F back to °C before storing
  if ACell.Column = TempColumn then
    AValue := TValue.From<Double>((AValue.AsExtended - 32) * 5 / 9);
end;

procedure TForm1.GridCellEditValidateData(Sender: TObject;
  ACell: TTMSFNCDataGridCellCoord;
  AInplaceEditor: TTMSFNCDataGridInplaceEditor;
  var AValue: TTMSFNCDataGridCellValue;
  var AValid: Boolean);
begin
  // Reject negative temperatures in Kelvin column
  if ACell.Column = KelvinColumn then
    AValid := AValue.AsFloat >= 0;
end;

Tip: OnCellEditGetData and OnCellEditSetData are the right place for unit conversions, lookup formatting, or any round-trip transform. For simple validation (range checks, required fields), OnCellEditValidateData is cleaner than OnBeforeCloseInplaceEditor because it receives the parsed TValue rather than a raw string.

Keyboard lookup

Keyboard lookup moves the focused cell to the first matching value while editing is disabled.

Grid.Options.Editing.Enabled := False;
Grid.Options.Lookup.Enabled := True;
Grid.Options.Lookup.Incremental := True;
Grid.Options.Lookup.CaseSensitive := False;
Grid.Options.Lookup.ResetInterval := 4000;

Programmatic lookup is available too:

Grid.Lookup('Smith', True, True);
Grid.LookupInColumn(1, 'Smith');
Grid.LookupInColumnFromRow(1, 5, 'Smith');

Use OnBeforeLookup to modify or cancel the search string:

procedure TForm1.GridBeforeLookup(Sender: TObject;
  var ALookupString: string; var ACanLookup: Boolean);
begin
  if Length(ALookupString) < 2 then
    ACanLookup := False;
end;
  • TTMSFNCDataGrid.Options.Editing
  • TTMSFNCDataGrid.Options.Lookup
  • TTMSFNCDataGrid.Lookup
  • TTMSFNCDataGrid.LookupInColumn
  • TTMSFNCDataGrid.LookupInColumnFromRow
  • OnBeforeOpenInplaceEditor / OnAfterOpenInplaceEditor
  • OnBeforeInplaceEditorGetValue / OnAfterInplaceEditorGetValue
  • OnBeforeInplaceEditorSetValue / OnAfterInplaceEditorSetValue
  • OnBeforeCloseInplaceEditor / OnAfterCloseInplaceEditor
  • OnBeforeExitInplaceEditor / OnAfterExitInplaceEditor
  • OnCellEditGetData — data-level: override the value loaded into the editor.
  • OnCellEditSetData — data-level: transform the value before it is written back.
  • OnCellEditValidateData — data-level: reject invalid values with AValid := False.
  • OnBeforeLookup / OnAfterLookup

See also