DataGrid

DataGrid is bound to a dataset and record load mode is set to loadall.

I try to add a new column with a button. And I try to add a button to a cell. Both does not work.

grdData.AddButtonColumn(5,'Delete');
grdData.AddButton(2,3,'Delete');

What am I missing?

tx Bernd

Can you share at which point you call the code to configure the column? You might need to first activate the adapter and then afterwards configure the columns

Pieter, thank you for the quick response. :- )

Demo attached.

DataBinding2Way.zip (75.7 KB)

Ok, the issue is that properties set on cells while connected to the dataset are lost in memory. So you'll have to configure the column, or at least make sure the grid can load settings from memory. There are several ways to do this, one is setting properties at column level:

procedure TForm3.SetupGrid;
begin
  grdData.Options.Sorting.Enabled := True;
  grdData.Columns[3].&Type := gcitButton;
  grdData.Columns[3].&TypeRange := gcirNormal;
  grdData.Columns[3].AddSetting(gcsType);
end;

Also, I use column index 3 (fourth column), since you only have 4 columns, not 5. To add a button to an individual cell you can add a custom cell class including a button.

unit Unit3;

interface

uses
  System.SysUtils,
  System.Types,
  System.UITypes,
  System.Classes,
  System.Variants,
  FMX.Types,
  FMX.Controls,
  FMX.Forms,
  FMX.Graphics,
  FMX.Dialogs,
  Data.Bind.Controls,
  Data.Bind.Components,
  Data.Bind.DBScope,
  Data.DB,
  Datasnap.DBClient,
  FMX.Layouts,
  Fmx.Bind.Navigator,
  FMX.Controls.Presentation,
  FMX.Edit,
  FMX.TMSFNCEdit,
  FMX.TMSFNCTypes,
  FMX.TMSFNCUtils,
  FMX.TMSFNCGraphics,
  FMX.TMSFNCGraphicsTypes,
  FMX.TMSFNCCustomComponent,
  FMX.TMSFNCDataBinding,
  FMX.TMSFNCCustomControl,
  FMX.TMSFNCListBox,
  FireDAC.Stan.Intf,
  FireDAC.Stan.Option,
  FireDAC.Stan.Param,
  FireDAC.Stan.Error,
  FireDAC.DatS,
  FireDAC.Phys.Intf,
  FireDAC.DApt.Intf,
  FireDAC.Comp.DataSet,
  FireDAC.Comp.Client,
  FMX.ListBox, FMX.StdCtrls, FMX.TMSFNCCustomPicker, FMX.TMSFNCDatePicker,
  FMX.EditBox, FMX.SpinBox, System.Rtti, FMX.TMSFNCDataGridCell,
  FMX.TMSFNCDataGridData, FMX.TMSFNCDataGridBase, FMX.TMSFNCDataGridCore,
  FMX.TMSFNCDataGridRenderer, FMX.TMSFNCDataGridDatabaseAdapter,
  FMX.TMSFNCDataGrid;

type
  TForm3 = class(TForm)
    edVorname: TTMSFNCEdit;
    BindNavigator1: TBindNavigator;
    DataSource1: TDataSource;
    BindSourceDB1: TBindSourceDB;
    TMSFNCListBox1: TTMSFNCListBox;
    TMSFNCDataBinder1: TTMSFNCDataBinder;
    FDMemTable1: TFDMemTable;
    FDMemTable1ID: TIntegerField;
    FDMemTable1Vorname: TStringField;
    FDMemTable1Zuname: TStringField;
    FDMemTable1GebDat: TDateField;
    edZuname: TTMSFNCEdit;
    lblVorname: TLabel;
    lblZuname: TLabel;
    dtGebDat: TTMSFNCDatePicker;
    spID: TSpinBox;
    grdData: TTMSFNCDataGrid;
    TMSFNCDataGridDatabaseAdapter: TTMSFNCDataGridDatabaseAdapter;
    DataSource: TDataSource;
    procedure BindControls;
    procedure CreateData;
    procedure FormCreate(Sender: TObject);
    procedure SetupGrid;
    procedure grdDataGetCellClass(Sender: TObject; AColumn, ARow: Integer;
      var ACellClass: TTMSFNCDataGridCellClass);
    procedure grdDataGetCellProperties(Sender: TObject;
      ACell: TTMSFNCDataGridCell);
    procedure grdDataCellButtonClick(Sender: TObject; AColumn, ARow: Integer);
  private
  { Private-Deklarationen }
  public
  { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

{$R *.fmx}

procedure TForm3.BindControls;
begin
  TMSFNCDataBinder1.ConnectSingle(edVorname, DataSource1, 'Text', 'Vorname');
  TMSFNCDataBinder1.ConnectSingle(edZuname, DataSource1, 'Text', 'Zuname');
  TMSFNCDataBinder1.ConnectSingle(dtGebDat, DataSource1, 'SelectedDate', 'Gebdat');
  TMSFNCDataBinder1.ConnectSingle(spID, DataSource1, 'Text', 'ID');
  TMSFNCDataBinder1.ConnectList(TMSFNCListBox1, DataSource1, 'Items', ['Text'],['Zuname']);
  TMSFNCDataBinder1.Active := True;
end;

procedure TForm3.CreateData;
var
  I: Integer;
begin
  FDMemTable1.Open;
  for I := 1 to 20 do begin
    FDMemTable1.InsertRecord([100 + i, 'Bernd' + i.ToString, 'Maierhofer' + i.ToString, Now - 55 + i]);
    FDMemTable1.InsertRecord([200 + i, 'Oskar'+i.ToString, 'Test' + i.ToString, Now - 25 + i]);
  end;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  CreateData;
  BindControls;
  SetupGrid;
  FDMemTable1.First;
end;

procedure TForm3.grdDataCellButtonClick(Sender: TObject; AColumn,
  ARow: Integer);
begin
  ShowMessage('Button ' + MakeCell(AColumn, ARow).ToString + ' clicked!');
end;

procedure TForm3.grdDataGetCellClass(Sender: TObject; AColumn, ARow: Integer;
  var ACellClass: TTMSFNCDataGridCellClass);
begin
  if (AColumn = 2) and (ARow = 3) then
    ACellClass := TTMSFNCDataGridButtonCell;
end;

procedure TForm3.grdDataGetCellProperties(Sender: TObject;
  ACell: TTMSFNCDataGridCell);
begin
  if ACell.IsButtonCell then
  begin
    if ACell.Coordinate.IsEqualTo(MakeCell(2, 3)) then
      ACell.AsButtonCell.Button.Text := 'Delete'
    else
      ACell.AsButtonCell.Button.Text := 'Click Me';
  end;
end;

procedure TForm3.SetupGrid;
begin
  grdData.Options.Sorting.Enabled := True;
  grdData.Columns[3].&Type := gcitButton;
  grdData.Columns[3].&TypeRange := gcirNormal;
  grdData.Columns[3].AddSetting(gcsType);
end;

end.

Unit3.zip (82.1 KB)

I see. So the problem is, that the setup of the columns get lost as soon as the data is fetched? Because of auto create columns?

The add methods, or any programmatic access to cell data is stored in cell memory, but as soon as the dataset changes, the cells are reconfigured to make sure the data is properly retrieved. when connected to a database adapter, most of the stuff happens virtual (read in memory), therefore settings at cell level get lost.