Как обновить значения полей набора данных, используя измененные данные в пользовательских 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;

Я далек от того, чтобы думать, что этот путь оптимален, и буду благодарен за любые комментарии и идеи, как оптимизировать код.

Другие вопросы по тегам