如果在运行时设置数据源的数据集属性时,如何使用TStringGrid以外的控件与Livebindings一起正常工作?我可以让TStringGrid识别数据集字段,但不能识别其他控件,如TEdit。
以下是我的项目的详细信息。我创建了一个数据模块和一个表单。具有数据集对象和表单的数据模块具有数据源和UI控件。为了减少模块之间的依赖关系,我不希望表单单元使用数据模块单元。相反,我想在运行时设置datasource.dataset。如果我使用TStringGrid,这个策略可行,但是对于TEdit,它没有。我尝试在LiveBindings中手动创建字段,但这些字段不会映射到数据集。如果我使用VCL,这将是一个非问题,但我一直无法找到使用Livebindings实现这一目标的最佳方法。仅供参考,这是一个FMX项目。
我还注意到,如果我“使用”数据模块来创建Livebinding连接并随后将其使用,则字段显示在BindSourceDb上并读取(无效)。当我运行应用程序并在运行时设置dataset属性时,TEdit控件能够找到一个可以正常工作的字段。如何在不使用和使用模块的情况下做任何建议?
答案 0 :(得分:0)
使用LiveBindings,以下项目对我来说很好。我做了我 理解你要描述,即
Form单元DynLiveBindingsu最初使用数据模块单元DynDMu。在那种情况下, 我将实时绑定组件添加到表单并“连接起来”,从开始 填充BindingList对象,然后使用它添加TLinkGridToDataSource和TLinkControlToField并设置它们的属性。
然后,我从表单的Uses列表中删除了对DynDMu的引用,编译 并运行该项目并将StringList1和Edit1正确绑定到 数据模块中的数据集。
显然我看不到你的项目,所以不知道你为什么会遇到问题, 但至少这个答案给你一个工作项目作为一个基础 与你的比较。
请注意,顺便说一句,在数据模块或表格中没有涉及TDataSource。
我正在使用Delphi Seattle,顺便说一句。
DataModule的:
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
答案 1 :(得分:0)
马丁,
这没有解决我的问题。我根本不想将数据模块单元放在我的使用部分。相反,我想通过设置datasource.dataset来“注入”数据集。
我能够找到解决方案。它涉及使linkControltoField1属性通过将其active属性设置为false来“刷新”,然后在设置dataset属性后设置为true。这是我的代码。 (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.