Uses OnCheckChange
to keep a related field in sync whenever a boolean field is toggled from
the grid, and to optionally veto the change.
An Active boolean field. When a row is switched off, its
Priority field (an integer, used for a separate work queue)
should be cleared to zero at the same time, so both fields land in the
dataset together.
procedure TfrmOrders.GridCheckChange(Column: TColumn);
begin
if Column.FieldName <> 'Active' then Exit;
// OnCheckChange fires BEFORE the field is flipped: Column.Field.AsBoolean
// is still the OLD value here, so the value about to be set is its
// negation, not the value already in the field.
//
// The dataset is also not yet in edit state at this point (see "Why it
// works this way" below) - Table.Edit is required before touching
// Priority, or this raises "Dataset not in edit or insert mode".
// Calling Edit when already editing is harmless, so this is always safe.
Table.Edit;
if Column.Field.AsBoolean then // about to become False
Table.FieldByName('Priority').AsInteger := 0;
end;
Column.Field.AsBoolean above is still the value the
checkbox showed before this click, and the dataset is not even in edit
state yet at this point. Reason about the checkbox as “about to become
not Column.Field.AsBoolean”, not “has just become
something”.Table.Edit is required here: unlike a
normal keystroke edit, the grid only puts the dataset into edit state
for the Active field’s own toggle after
OnCheckChange returns - not before. Writing to
Priority without calling Edit first raises an
exception. Both fields still end up posted together afterward, in the
grid’s own automatic Post call once the checkbox’s own
toggle completes - no separate Table.Post is needed in the
handler, only the Edit.procedure TfrmOrders.GridCheckChange(Column: TColumn);
begin
if (Column.FieldName = 'Active') and Column.Field.AsBoolean
and (Table.FieldByName('OpenTickets').AsInteger > 0) then
raise Exception.Create('Nao e possivel desactivar: existem tickets em aberto.');
end;
TEgColumn.OnCheckChange is
the column-scoped equivalent, firing after the grid-level handler when
both are assigned - attach it directly to the Active column
instead of checking Column.FieldName in a grid-wide
handler, if this logic only ever applies to that one column.