delphi - 将 TCombobox 列添加到 Firemonkey TGrid

标签 delphi firemonkey

这个问题似乎已经得到了回答,可能是由 MonkeyStyler/Mike Sutton 回答的,但是,由于我使用的是 Delphi 10 Seattle,所以提供的代码和指南不再起作用。具体来说

firemonkey grid basics

不起作用,因为 ApplyStyling 事件处理程序现在仅调用一次(在创建列时)

我想向 aTGrid 添加 TCombobox 或 TComboboxEdit 列。

type
  TComboColumn = Class(TColumn)
  protected
    function CreateCellControl: TStyledControl; override; // works!
  End;

...

Grid1.AddObject(TComboColumn.Create(Grid1)); 

...

    function TComboColumn.CreateCellControl: TStyledControl;
    begin
      Result := TComboBox.Create(Self);
      TComboBox(Result).Items.Add('A');
      TComboBox(Result).Items.Add('B');
      TComboBox(Result).Items.Add('C');
      TComboBox(Result).OnChange := DoTextChanged; // strange hooks
    end;

这会在网格中创建组合框列,但每行中的组合框都是相同的,而且我不知道如何添加适用于此处的 GetValue 和 SetValue 方法。

最佳答案

你需要做很多事情。开始吧。 首先,您需要声明一些数据类型来存储 ComboBox 的值。专栏。

  TComboRecord = record
    FieldValues: array of string;
    ItemSelected: integer;
    function Selected: string;
  end;


...
{ TComboRecord }

function TComboRecord.Selected: string;
begin
  Result := FieldValues[ItemSelected];
end;

并填充TList<TComboRecord>一些数据。

var
  ComboData: TList<TComboRecord>;
procedure PopulateComboData(Rows: cardinal);

implementation

procedure PopulateComboData(Rows: cardinal);
var
  RowI: cardinal;
  i: cardinal;
  ComR: TComboRecord;
begin
  for RowI := 1 to Rows do
  begin
    Setlength(ComR.FieldValues, random(5) + 1);
    for i := 0 to length(ComR.FieldValues) - 1 do
      ComR.FieldValues[i] := inttostr(random(64000));
    ComR.ItemSelected := 0;
    ComboData.Add(ComR);
  end;
end;

initialization

ComboData := TList<TComboRecord>.Create;

finalization

ComboData.Free;

您需要创建一个 TComboBox上升,以便它可以存储和操作 TComboRecord输入数据。

  TComboBoxCell = class(TComboBox)
  private
    FComboData: TComboRecord;
    procedure SetComboData(const Value: TComboRecord);
    function GetComboData: TComboRecord;
  protected
    procedure SetData(const Value: TValue); override;
  public
    property ComboData: TComboRecord read GetComboData write SetComboData;
  end;
...

{ TComboBoxCell }


function TComboBoxCell.GetComboData: TComboRecord;
begin
  FComboData.ItemSelected:=ItemIndex;
  result:=FComboData;
end;

procedure TComboBoxCell.SetComboData(const Value: TComboRecord);
var
  s: string;
begin
  FComboData := Value;
  Items.Clear;
  for s in Value.FieldValues do
    Items.Add(s);
  ItemIndex := Value.ItemSelected;
end;

procedure TComboBoxCell.SetData(const Value: TValue);
begin
  inherited;
  ComboData := Value.AsType<TComboRecord>
end;

比你需要继承一个新的类形式TColumn :

  TComboColumn = class(TColumn)
  protected
    procedure DoComboChanged(Sender: TObject);
    function Grid: TComboExtendedGrid; overload;
    function CreateCellControl: TStyledControl; override; 
  end;
...

{ TComboColumn }

function TComboColumn.CreateCellControl: TStyledControl;
begin
  Result := TComboBoxCell.Create(Self);
  TComboBoxCell(Result).OnChange := DoComboChanged;
end;

procedure TComboColumn.DoComboChanged(Sender: TObject);
var
  P: TPointF;
  LGrid: TComboExtendedGrid;
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),
    TValue.From<TComboRecord>(TComboBoxCell(Sender).ComboData));
  if Assigned(LGrid.FOnEditingDone) then
    LGrid.FOnEditingDone(Grid, Trunc(P.X), Trunc(P.Y));
end;

function TComboColumn.Grid: TComboExtendedGrid;
var
  P: TFmxObject;
begin
  Result := nil;
  P := Parent;
  while Assigned(P) do
  begin
    if P is TCustomGrid then
    begin
      Result := TComboExtendedGrid(P);
      Exit;
    end;
    P := P.Parent;
  end;
end;

你看,现在我们必须子类型 TGrid类以及我们必须通过 Grid 获取它的处理程序功能并需要访问 protected FOnEditingDone变量

  TComboExtendedGrid = class(TGrid)
  private
    FOnEditingDone: TOnEditingDone;
  protected
    procedure SetValue(Col, Row: integer; const Value: TValue); override;
  end;
{ TComboExtendedGrid }

procedure TComboExtendedGrid.SetValue(Col, Row: integer; const Value: TValue);
begin
  inherited;

end;

最后,我们需要在表单单元中设置必要的创建和事件处理机制。将列变量添加到 from 声明中。

  protected
    CCColumn:TComboColumn;

填充 ComboData 并创建列:

procedure TForm1.Button1Click(Sender: TObject);
begin
  PopulateComboData(Grid2.RowCount);
  CCColumn:=TComboColumn.Create(Grid2);
  CCColumn.Parent := Grid2;
  CCColumn.Header := 'CB';
end;

并处理事件:

procedure TForm1.Grid2GetValue(Sender: TObject; const Col, Row: Integer;
  var Value: TValue);
begin
  case Col of
     6{Combo Column Number}: Value:=TValue.From<TComboRecord>(ComboData[Row])
  end;
end;

procedure TForm1.Grid2SetValue(Sender: TObject; const Col, Row: Integer;
  const Value: TValue);
begin
  case Col of
      6{Combo Column Number}: ShowMessage(Value.AsType<TComboRecord>.Selected);
  end;
end;

不要忘记将更改(如果需要)传递给 ComboData列表。当前的处理程序不会为您执行此操作。我更喜欢在 Grid2SetValue 中制作这个事件处理程序。

关于delphi - 将 TCombobox 列添加到 Firemonkey TGrid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32920219/

相关文章:

android - 德尔福 XE5 Firemonkey : Single code base for mobile/Win/OSX?

android - 为什么当手指触摸屏幕时 Android 上的计时器更准确?

delphi - 通过存储过程处理 Blob 数据

xml - 在Delphi 10.1中生成XML文件并执行基本的XML操作?

Delphi - idFTP获取当前目录

delphi - 为什么滚动 TListView 需要整个表单重新绘制 - Delphi Firemonkey

delphi - 如果某些 Delphi SOAP RTL OpConvert.pas 方法使用 String 而不是 Stream 作为其 XML 文档类型,为什么它们会被弃用?

xml - 在 Delphi 2010 中从 XML 读取°度数符号

android - 为什么 Android FireMonkey 应用程序中的控件不能跨越多列或多行?

android - 从内部存储中删除文件