1

我正在尝试将一些自定义列添加到 TGrid,例如将包含 TCalendarEdit 的列并将其实时绑定到 DB。
我想出了两种方法来实现这样的事情。

  1. 将 CalendarEdit 放在所有行中。
    问题是:我可以创建自定义 TCalendarEdit 列, 可以将其放入 Grid 中, 但随后我将它绑定到数据集 ,它会下降到默认字符串列视图!
    TDateColumn = class(TColumn)
    protected
    function CreateCellControl: TStyledControl; override;
    end;
    function TDateColumn.CreateCellControl: TStyledControl;
    begin
    Result := TDateCell.Create(grid);
    Result.Parent := grid;
    end;


    procedure TForm1.FormCreate(Sender: TObject);
    var
    cec: TDateColumn;
    begin
    cec:=TDateColumn.Create(grid1);
    grid1.AddObject(cec);
    end;

    LinkGridToDataSource1.Columns.Items[LinkGridToDataSource1.Columns.Count-1].MemberName:='date';

  2. 在网格单元格上绘制一个控件,然后单击并销毁它,然后单击网格上的任何其他位置(并将其数据写入网格)。
    问题是:如何获取单元格 OnClick 的坐标和大小?

谢谢你。

4

3 回答 3

1

我只有第一部分的解决方案。由于原始源代码中奇怪的 ColumnCreate 实现,这有点棘手。

什么原因?

查看单元Fmx.Bind.Grid(Win32 上的路径%programfiles%\Embarcadero\RAD Studio\10.0\source\databinding\components)和方法(从第 500 行开始)

function TLinkGridToDataSourceControlManager.CreateColumn( 
  const ADescription : TCreateColumnDescription; AGrid : TCustomGrid ) : TColumn;

列是相对于ADescription.ColumnStyle或如果为空而创建的ADescription.MemberType。但它不是基于注册的类,它是硬编码的。

这很奇怪,因为 ColumnStyleName 是从没有前导的 ColumnClass 构建的T(例如 Class TStringColumn=> ColumnStyle StringColumn)。

为什么 Emba 不直接根据 ColumnStyle 搜索已注册的 Classes?

FindClass( 'T' + ADescription.ColumnStyle )

如果是这样,您可以注册自己的 ColumnClasses TMyColumn,将 ColumnStyle 属性设置为MyColumn,一切都会好起来的。您无法在 PropertyEditor 中看到此 ColumnStyle,除非您将此 ColumnClass 作为包安装(不,这不会起作用,因为 PropertyEditor 也是硬编码的),但谁在乎它可以在 OI 中设置。

让我们变得灵活

要解决此问题,您必须手动执行一些步骤

  1. 复制Fmx.Bind.Grid.pas到新路径(项目确实或有效的 Delphi 搜索/库路径)
  2. 将其重命名为Fmx.Bind.GridAdv.pas
  3. 现在您必须在此副本中替换Fmx.Bind.Grid为at 行Fmx.Bind.GridAdv

    9、10、455 号线

  4. 为了获得内部的灵活性,请替换它(从第 500 行开始)

    function TLinkGridToDataSourceControlManager.CreateColumn(
      const ADescription: TCreateColumnDescription; AGrid: TCustomGrid): TColumn;
    begin
      Result := nil;
      if ADescription.ColumnStyle <> '' then
    

    有了这个

    function TLinkGridToDataSourceControlManager.CreateColumn( 
      const ADescription : TCreateColumnDescription; AGrid : TCustomGrid ) : TColumn;
     // ** MOD START **
     type
       TColumnClass = class of TColumn;
     var
       LColumnClass : TColumnClass;
     // ** MOD END **
     begin
       Result := nil;
       if ADescription.ColumnStyle <> '' then
     // ** MOD START **
         begin
           LColumnClass := TColumnClass( FindClass( 'T' + ADescription.ColumnStyle ) );
           if LColumnClass <> nil
           then
             begin
               Result := LColumnClass.Create( FCustomGrid );
             end else 
     // ** MOD END **
    

    下面的一些行我们必须关闭begin

    // ** MOD START **
        end;
    
    // ** MOD END **
    
      if Result = nil then
        case ADescription.MemberType of
    
  5. 保存文件

自定义列

作为示例,我将使用一个简单的TNumberColumn衍生自TStringColumn. 请记住,您必须注册自定义列类。

unit FMX.Grid.Columns;

interface

uses
  FMX.Grid, FMX.Types, FMX.Menus;

type
  TNumberColumn = class( TStringColumn )
  protected
    function CreateCellControl : TStyledControl; override;
  end;

implementation

{ TNumberColumn }

function TNumberColumn.CreateCellControl : TStyledControl;
begin
  Result                            := inherited;
  ( Result as TTextCell ).TextAlign := TTextAlign.taTrailing;
end;

initialization

RegisterFmxClasses( [TNumberColumn] );

end.

如何使用?

只需像往常一样创建表单并使用网格为某些列创建绑定。

要让我们的补丁运行,您必须注意使用顺序。修补的单元必须在原始单元之后。

unit Main_ViewU;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Grid,
  FMX.Layouts, Data.Bind.GenData, Data.Bind.EngExt, FMX.Bind.DBEngExt,

  FMX.Bind.Grid, // <-- original unit
  FMX.Bind.GridAdv, // <-- patched unit

  FMX.Grid.Columns, // CustomColumns unit

  System.Bindings.Outputs, FMX.Bind.Editors,
  Data.Bind.Components, Data.Bind.Grid, Data.Bind.ObjectScope;

type
  TForm1 = class( TForm )
    Grid1 : TGrid;
    DataGeneratorAdapter1 : TDataGeneratorAdapter;
    AdapterBindSource1 : TAdapterBindSource;
    BindingsList1 : TBindingsList;
    LinkGridToDataSource1 : TLinkGridToDataSource;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1 : TForm1;

implementation

{$R *.fmx}

end.

最后一步,只需将某些列设置为ColumnStyleNumberColumn运行程序以查看这些列是否正确对齐。

除了 Fmx.Bind.GridAdv.pas 之外的完整示例项目源

于 2013-01-08T17:19:42.450 回答
0

我不知道您的单元格或列的代码是什么,但我希望在下面看到类似的内容。

您可以在单元格中的 MouseDown 中做任何您想做的事情。如果您希望在列中处理它,请创建一个事件并在 CreateCellControl 中设置它:

type TDateCell = class(TCalendarEdit)
  protected
    procedure MouseDown(Button: TMouseButton;Shift: TShiftState;X, Y: Single);override;
  end;

type TDateColumn = class(TColumn)
  protected
    function CreateCellControl: TStyleControl;override;
  end;

procedure TDateCell.MouseDown(Button: TMouseButton;Shift: TShiftState;X, Y: Single)
begin
  inherited;
  //Custom stuff here with X,Y
end;

function TDateColumn.CreateCellControl: TStyledControl;
begin
  Result := TDateCell.Create;
  Result.Parent := Self;
end;
于 2012-09-28T14:49:44.983 回答
0

Livebindings 控制网格列和单元格的创建,因此对列和 bindmanager 和其他 livebinding 组件进行子类化可能既不实用也不优雅。使用你所拥有的。

您可以访问网格 OnPainting 事件中的单元格

Somecell := TTextCell(Grid1.Columns[Col].Children[Row]);

您可能希望将 TextCell 设置为 Visible := False 并在同一位置创建您的 TCalendarEdit(所有者是表单,父项是列)。使用 TextCell.Text 将日期写入 CalendarEdit。

于 2013-10-28T08:41:22.013 回答