0

当在运行时设置其 Datasource 的 Dataset 属性时,如何让 TStringGrid 以外的控件与 Livebindings 一起正常工作?我可以获得一个 TStringGrid 来识别数据集字段,但不能识别其他控件,例如 TEdit。

这是我的项目的详细信息。我创建了一个数据模块和一个表单。具有数据集对象和表单的数据模块具有数据源以及 UI 控件。为了减少模块之间的依赖关系,我不希望表单单元使用数据模块单元。相反,我想在运行时设置 datasource.dataset。如果我使用 TStringGrid,则此策略有效,但使用 TEdit,则无效。我尝试在 LiveBindings 中手动创建字段,但这些字段并未映射到数据集。如果我使用 VCL,这将不是问题,但我一直无法找出使用 Livebindings 完成此任务的最佳方法。仅供参考,这是一个 FMX 项目。

我还注意到,如果我“使用”数据模块来创建 Livebinding 连接并随后未使用它,则字段会显示在 BindSourceDb 上并读取(无效)。当我运行应用程序并在运行时设置数据集属性时,TEdit 控件能够找到可以正常工作的字段。有什么建议如何在不使用和使用模块的情况下做到这一点?

4

2 回答 2

0

以下项目使用 LiveBindings 对我来说效果很好。我做了我理解你所描述的,即

  • 表单单元 DynLiveBindingsu 最初使用了数据模块单元 DynDMu。在这种情况下,我将实时绑定组件添加到表单并“将它们连接起来”,首先填充一个 BindingList 对象,然后使用它添加一个 TLinkGridToDataSource 和 TLinkControlToField 并设置它们的属性。

  • 然后,我从表单的 Uses 列表中删除了对 DynDMu 的引用,编译并运行了项目,并且 StringList1 和 Edit1 正确绑定到数据模块中的数据集。

显然我看不到您的项目,所以不知道您为什么会遇到问题,但至少这个答案为您提供了一个工作项目,可用作与您的项目进行比较的基础。

请注意,顺便说一句,在数据模块或表单中都没有涉及 TDataSource。

我正在使用德尔福西雅图,顺便说一句。

数据模块:

unit DynDMu;
[...]
type
  TDataModule1 = class(TDataModule)
    CDS1: TClientDataSet;
    CDS1Name: TStringField;
    CDS1ID: TIntegerField;
    procedure DataModuleCreate(Sender: TObject);
  end;

[...]

procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
  CDS1.CreateDataSet;
  CDS1.InsertRecord([1, 'One']);
  CDS1.InsertRecord([2, 'Two']);
  CDS1.InsertRecord([3, 'Three']);
end;

表格单元

unit DynLiveBindingsu;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.Bind.EngExt,
  Vcl.Bind.DBEngExt, Vcl.Bind.Grid, System.Rtti, System.Bindings.Outputs,
  Vcl.Bind.Editors, Data.Bind.Components, Data.Bind.DBScope, Data.Bind.Grid,
  Data.DB, Vcl.StdCtrls, Vcl.Grids, Data.Bind.Controls, Vcl.ExtCtrls,
  Vcl.Buttons, Vcl.Bind.Navigator;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Edit1: TEdit;
    BindingsList1: TBindingsList;
    LinkGridToDataSource1: TLinkGridToDataSource;
    BindSourceDB1: TBindSourceDB;
    BindNavigator1: TBindNavigator;
    LinkControlToField1: TLinkControlToField;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.

表格 DFM

object Form1: TForm1
[...]
  object StringGrid1: TStringGrid
  [...]
  end
  object Edit1: TEdit
  [...]
  end
  object BindNavigator1: TBindNavigator
    Left = 16
    Top = 150
    Width = 240
    Height = 25
    DataSource = BindSourceDB1
    Orientation = orHorizontal
    TabOrder = 2
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 216
    Top = 184
    object LinkGridToDataSource1: TLinkGridToDataSource
      Category = 'Quick Bindings'
      DataSource = BindSourceDB1
      GridControl = StringGrid1
      Columns = <
        item
          MemberName = 'ID'
        end
        item
          MemberName = 'Name'
        end>
    end
    object LinkControlToField1: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceDB1
      FieldName = 'Name'
      Control = Edit1
      Track = False
    end
  end
  object BindSourceDB1: TBindSourceDB
    DataSet = DataModule1.CDS1
    ScopeMappings = <>
    Left = 296
    Top = 184
  end
end
于 2016-09-25T17:13:29.663 回答
0

马丁,

这没有解决我的问题。我根本不想将数据模块单元放在我的使用部分中。相反,我想通过设置 datasource.dataset 来“注入”数据集。

我能够找到解决方案。它涉及通过将其 active 属性设置为 false 并在设置 dataset 属性后设置为 true 来使 linkControltoField1 属性“刷新”。这是我的代码。(D10.1 柏林)

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti, System.Bindings.Outputs,
  Vcl.Bind.Editors, Data.Bind.EngExt, Vcl.Bind.DBEngExt, FireDAC.Stan.Intf,
  FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS,
  FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt,
  FireDAC.UI.Intf, FireDAC.VCLUI.Wait, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Phys, FireDAC.Phys.MSAcc, FireDAC.Phys.MSAccDef, Data.Bind.Controls,
  Vcl.ExtCtrls, Vcl.Buttons, Vcl.Bind.Navigator, Data.DB, FireDAC.Comp.Client,
  FireDAC.Comp.UI, FireDAC.Comp.DataSet, Data.Bind.Components, Vcl.StdCtrls,
  Data.Bind.DBScope, Data.Bind.ObjectScope, Vcl.Bind.Grid, Data.Bind.Grid,
  Vcl.Grids;

type
  TForm1 = class(TForm)
    BindSourceDB1: TBindSourceDB;
    Edit1: TEdit;
    BindingsList1: TBindingsList;
    DataSource1: TDataSource;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    NavigatorBindSourceDB1: TBindNavigator;
    StringGrid1: TStringGrid;
    LinkGridToDataSourceBindSourceDB1: TLinkGridToDataSource;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    LinkControlToField1: TLinkControlToField;
    procedure Button1Click(Sender: TObject);
  private
    function GetDataset: Tdataset;
    procedure SetDataset(const Value: Tdataset);
    { Private declarations }
  public
    { Public declarations }
    property Dataset: Tdataset read GetDataset write SetDataset;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  BindSourceDb1.DataSource := DataSource1;
  LinkControlToField1.DataSource := BindSourceDB1;
  LinkControlToField1.Active := False;   //in order for this to work you must
  LinkControlToField1.Active := True;    // set link to false then to true

end;

function TForm1.GetDataset: Tdataset;
begin
  Result := Datasource1.DataSet;
end;

procedure TForm1.SetDataset(const Value: Tdataset);
begin
  Datasource1.DataSet := Value;
  BindSourceDb1.DataSource := DataSource1;
  LinkControlToField1.DataSource := BindSourceDB1;
  LinkControlToField1.Active := False;   //in order for this to work you must
  LinkControlToField1.Active := True;    // set link to false then to true
end;

end.

这是文本中的dfm文件。

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Edit1: TEdit
    Left = 184
    Top = 88
    Width = 121
    Height = 21
    TabOrder = 0
  end
  object NavigatorBindSourceDB1: TBindNavigator
    Left = 280
    Top = 24
    Width = 240
    Height = 25
    DataSource = BindSourceDB1
    Orientation = orHorizontal
    TabOrder = 1
  end
  object StringGrid1: TStringGrid
    Left = 168
    Top = 112
    Width = 320
    Height = 120
    ColCount = 1
    FixedCols = 0
    RowCount = 2
    TabOrder = 2
    ColWidths = (
      64)
    RowHeights = (
      24
      24)
  end
  object Button1: TButton
    Left = 208
    Top = 256
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 3
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 352
    Top = 256
    Width = 75
    Height = 25
    Caption = 'Button2'
    TabOrder = 4
  end
  object Button3: TButton
    Left = 464
    Top = 256
    Width = 75
    Height = 25
    Caption = 'Button3'
    TabOrder = 5
  end
  object BindSourceDB1: TBindSourceDB
    ScopeMappings = <>
    Left = 432
    Top = 128
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 20
    Top = 5
    object LinkGridToDataSourceBindSourceDB1: TLinkGridToDataSource
      Category = 'Quick Bindings'
      DataSource = BindSourceDB1
      GridControl = StringGrid1
      Columns = <>
    end
    object LinkControlToField1: TLinkControlToField
      Category = 'Quick Bindings'
      FieldName = 'LastName'
      Control = Edit1
      Track = True
    end
  end
  object DataSource1: TDataSource
    Left = 496
    Top = 184
  end
  object FDGUIxWaitCursor1: TFDGUIxWaitCursor
    Provider = 'Forms'
    Left = 384
    Top = 64
  end
end

数据模块不起眼。只需一个 FDTable 和 FDconnection。我将它们附加到 dbDemos 数据库。注意 Unit1 不使用 Unit2。

unit Unit2;

interface

uses
  System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
  FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf,
  FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys, FireDAC.Phys.MSAcc,
  FireDAC.Phys.MSAccDef, FireDAC.VCLUI.Wait, Data.DB, FireDAC.Comp.Client,
  FireDAC.Comp.DataSet;

type
  TDataModule2 = class(TDataModule)
    FDTable1: TFDTable;
    FDConnection1: TFDConnection;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DataModule2: TDataModule2;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

end.

最后,这里是程序单元。这是我设置数据集属性的地方。

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {DataModule2: TDataModule};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TDataModule2, DataModule2);
  Application.CreateForm(TForm1, Form1);

  Form1.Dataset := Datamodule2.FDTable1;   //Injecting the dataset property

  Application.Run;
end.
于 2016-09-29T21:59:50.740 回答