Как обновить значения полей набора данных, используя измененные данные в пользовательских FMX TGrid coumns
Я использую следующий способ для определения и заполнения столбца ячейками-предшественниками TCalendarEdit (здесь часть интерфейса). Дайте мне знать, если мне нужно выставить реализацию.
type
TDynamicRecord = record
Field1, Field2, Field3: string;
DateSBU: TDate;
TimeSBU: TTime;
end;
TDateCell = class(TCalendarEdit)
protected
procedure SetData(const Value: TValue); override;
public
constructor Create(AOwner: TComponent); override;
end;
TDateColumn = class(TColumn)
protected
function CreateCellControl: TStyledControl; override;
public
constructor Create(AOwner: TComponent); override;
end;
Код отлично работает и столбец типа TDateColumn
можно добавить в сетку.
Я задал вопрос и открыл для него награду в поисках метода заполнения столбца, определенного пользователем, LiveBindings
но у меня нет ответов по истечении срока действия награды. Вот почему сейчас я пытаюсь по-другому. Я объявляю коллекцию DynamicData: TList<TDynamicRecord>;
и заполнить его из набора данных. Этот подход довольно четко объяснен в ответе @Mike-Sutton и в его блоге. Мне удалось это сделать. Данные правильно отображаются в сетке и во вновь определенных столбцах.
Но сейчас я застрял с другой проблемой. Мне нужно обновить набор данных о деятельности пользователя. Я попробовал OnSetValue
а также OnEditingDone
события родительской сетки (согласно документации эти события должны использоваться для обновления данных), но, как ни странно, она не срабатывает.
Что будет подходящим событием или другим способом, подходящим для обновления набора данных?
1 ответ
Я думаю, что проблема, по крайней мере частично, решена.
Пришлось перекрасить практически все классы. Я был бы рад, если бы кто-нибудь дал мне совет, как уменьшить полноту кода.
Я должен был объявить этот класс, чтобы выставить FOnEditingDone
а также procedure SetValue(...)
сделать их доступными:
type
TDynamicCustomGrid = class(TGrid)
private
FOnEditingDone: TOnEditingDone;
protected
procedure SetValue(Col, Row: Integer; const Value: TValue);override;
end;
implementation
procedure TDynamicCustomGrid.SetValue(Col, Row: Integer; const Value: TValue);
begin
inherited;
end;
Тогда я объявил
type
TDateColumn = class(TColumn)
protected
...
function Grid: TDynamicCustomGrid; overload;
procedure DoDateChanged(Sender: TObject);
public
...
end;
implementation
procedure TDateColumn.DoDateChanged(Sender: TObject);
var
P: TPointF;
LGrid: TDynamicCustomGrid;
begin
LGrid := Grid;
if not Assigned(LGrid) then
Exit;
if FUpdateColumn then
Exit;
if FDisableChange then
Exit;
P := StringToPoint(TFmxObject(Sender).TagString);
LGrid.SetValue(Trunc(P.X), Trunc(P.Y), TStyledControl(Sender).Data);
if Assigned(LGrid.FOnEditingDone) then
LGrid.FOnEditingDone(Grid, Trunc(P.X), Trunc(P.Y));
end;
function TDateColumn.Grid: TDynamicCustomGrid;
var
P: TFmxObject;
begin
Result := nil;
P := Parent;
while Assigned(P) do
begin
if P is TCustomGrid then
begin
Result := TDynamicCustomGrid(P);
Exit;
end;
P := P.Parent;
end;
end;
И наконец я назначил TDateCell(Result).OnChange := DoDateChanged;
в function TDateColumn.CreateCellControl: TStyledControl;
Я далек от того, чтобы думать, что этот путь оптимален, и буду благодарен за любые комментарии и идеи, как оптимизировать код.