【问题标题】:Firemonkey livebindings custom Grid columnsFiremonkey livebindings 自定义网格列
【发布时间】:2012-09-22 20:50:47
【问题描述】:

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

  1. 将 CalendarEdit 放在所有行中。
    问题是:我可以创建自定义 TCalendarEdit 列,
    TDateColumn = class(TColumn)
    protected
    function CreateCellControl: TStyledControl; override;
    end;
    function TDateColumn.CreateCellControl: TStyledControl;
    begin
    Result := TDateCell.Create(grid);
    Result.Parent := grid;
    end;

    可以放到Grid里,
    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. 在 Grid 单元格上绘制一个控件,然后单击并销毁它,然后单击 Grid 上的任何其他位置(并将其数据写入 Grid)。
    问题是:如何获取单元格 OnClick 的坐标和大小?

谢谢。

【问题讨论】:

  • Q1:您如何创建自定义单元格和列? Q2:我不确定你想在这里实现什么。
  • 感谢您的关注!我已经编辑了我的问题。这个问题仍然很热门。

标签: delphi firemonkey livebindings delphi-xe3


【解决方案1】:

我只得到了 first 部分的解决方案。由于原始源代码中奇怪的 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 是从没有前导 T 的 ColumnClass 构建的(例如 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 替换为 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. 保存文件

自定义列

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

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 并运行程序以查看这些列是否对齐。

Complete Sample Project Source except the Fmx.Bind.GridAdv.pas

【讨论】:

    【解决方案2】:

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

    你可以在单元格中的 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;
    

    【讨论】:

    • 不起作用,因为 TDateColumn 会下降到默认的列样式视图,然后它会实时绑定到数据集,因为 CUZ LinkGridToDataSource1 有自己的 columnstyle 属性覆盖 Grid 属性。因此,它只有在没有实时绑定到数据集时才有效。
    【解决方案3】:

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

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

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

    您可能希望将 TextCell 设置为 Visible := False 并在同一位置创建您的 TCalendarEdit(Owner 是 Form,Parent 是 Column)。使用 TextCell.Text 将日期写入 CalendarEdit。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 2022-11-20
      • 2012-03-09
      • 2014-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多