使用MasterSource的Delphi XE8 TBindSourceDB组件

问题描述 投票:0回答:1

问题是TBindSourceDB的MasterSource的正确用法是什么例如

1带有导航器的部门的ListView链接到TBindSourceDB(主数据库)。当按下导航器的“插入”按钮时,另一个列表视图变为活动状态,即城市列表视图。现在,带有另一个导航器的城市ListView链接到另一个TBindSourceDB,即城市(详细信息)。我需要将城市作为部门的主要来源。如何以及在哪里必须这样做?

两者,主要和详细TBindSourceDB都链接到具有MasterSource属性的Firedac TSimpleDataSet组件。我已经在指向主组件的细节上填充了该属性。问题是:当按下“详细”导航按钮插入时,TSimpleDataSet中的OnBeforePost会触发,因为它想执行Post!并且不会触发OnAfterInsert事件。使用Firemonkey和TBindSourceDB组件的工作主机->细节数据的正确模式是哪种?]

delphi data-binding sql-insert firemonkey
1个回答
0
投票

如果我理解您的正确要求,我认为下面的项目将向您展示有关添加主记录+明细记录的最重要的事情。我认为TListViews实际上分散了对所需内容的理解,因此我将不使用它们,而是使用一些TEdit来显示Master+详细信息一次记录一行。

根据我的经验,经验法则是避免使用LiveBindings做某事如果有更简单的方法可以做到这一点,那就是建立Master-> Master和Details之间的关系。

因此,表单上的组件列表中是一个TDataSource,它链接了二。它的DataSet属性连接到Master。在细节方面应将Detail的MasterSource属性设置为其,并将其MasterField属性设置为设置为Master的MasterID字段。

添加TDataSource的要点是,它使您能够使用标准TDataset模型及其支持的事件可完成建立所需的所有工作插入新的详细记录与当前MasterRecord之间的链接。这是在Detail的OnNewRecord事件中完成的,其内容如下:

procedure TMasterDetailForm.DetailNewRecord(DataSet: TDataSet);
begin
  Detail.FieldByName('DetailID').AsInteger := NextDetailID;
  Detail.FieldByName('MasterID').AsInteger := Master.FieldByName('MasterID').AsInteger;
  Detail.FieldByName('Name').AsString := Format('DetailID:%d for MasterID:%d ', [NextDetailID, Master.FieldByName('MasterID').AsInteger]);
  inc(NextDetailID);
end;

使用TDataSource的好处是,它可以确保正确的Master和Detail插入新的详细信息记录时同步。

唯一的其他重要代码在FormCreate evnt中,该代码用于创建和填充具有一些示例记录的Master和Detail数据集。所有LiveBindings连接在加载表单的DFM时设置。 DFM的摘录在项目源代码下方:

代码

unit MasterDetailListsu;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ListView.Types, Data.Bind.GenData,
  Fmx.Bind.GenData, System.Rtti, System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.EngExt, Fmx.Bind.DBEngExt,
  Data.Bind.Components, Data.Bind.ObjectScope, FMX.Objects, FMX.StdCtrls, FMX.ListView, FMX.ListView.Appearances,
  FMX.Layouts, FMX.MultiView,FMX.Memo, Fmx.Bind.Navigator, System.Actions, FMX.ActnList,
  FMX.ListView.Adapters.Base, Data.DB, Datasnap.DBClient,
  FMX.Controls.Presentation, FMX.TreeView, Data.Bind.DBScope, SimpleDS,
  Data.Bind.Controls, FMX.ListBox, FMX.Grid.Style, FMX.Grid, FMX.ScrollBox,
  FMX.Edit;

type
  TMasterDetailForm = class(TForm)
    Master: TSimpleDataSet;
    Detail: TSimpleDataSet;
    MasterMasterID: TIntegerField;
    MasterName: TStringField;
    DetailDetailID: TIntegerField;
    DetailMasterID: TIntegerField;
    DetailName: TStringField;
    BindSourceMaster: TBindSourceDB;
    NavigatorBindSourceDB1: TBindNavigator;
    BindingsList1: TBindingsList;
    BindGridLink1: TBindGridLink;
    edMasterID: TEdit;
    LinkControlToField1: TLinkControlToField;
    edMasterName: TEdit;
    LinkControlToField2: TLinkControlToField;
    edDetailID: TEdit;
    edDetailMasterID: TEdit;
    edDetailName: TEdit;
    LinkControlToField3: TLinkControlToField;
    BindSourceDetail: TBindSourceDB;
    LinkControlToField4: TLinkControlToField;
    BindNavigator1: TBindNavigator;
    DataSource1: TDataSource;
    LinkControlToField5: TLinkControlToField;
    procedure FormCreate(Sender: TObject);
    procedure DetailNewRecord(DataSet: TDataSet);
    procedure MasterNewRecord(DataSet: TDataSet);
  private
  public
    NextMasterID,
    NextDetailID : Integer;
  end;

[...]

procedure TMasterDetailForm.FormCreate(Sender: TObject);
var
  i,
  j : Integer;
begin

  Master.IndexFieldNames := 'MasterID';
  Master.CreateDataSet;

  Detail.IndexFieldNames := 'MasterID;DetailID';
  Detail.CreateDataSet;

  NextMasterID := 1;
  NextDetailID := 1;

  for i := 1 to 3 do begin
    Master.Insert;
    Master.Post;
    for j := 1 to 3 do begin
      Detail.Insert;
      Detail.Post;
    end;
  end;

  Master.First;

end;

procedure TMasterDetailForm.DetailNewRecord(DataSet: TDataSet);
begin
  Detail.FieldByName('DetailID').AsInteger := NextDetailID;
  Detail.FieldByName('MasterID').AsInteger := Master.FieldByName('MasterID').AsInteger;
  Detail.FieldByName('Name').AsString := Format('DetailID:%d for MasterID:%d ', [NextDetailID, Master.FieldByName('MasterID').AsInteger]);
  inc(NextDetailID);
end;

procedure TMasterDetailForm.MasterNewRecord(DataSet: TDataSet);
begin
  Master.FieldByName('MasterID').AsInteger := NextMasterID;
  Master.FieldByName('Name').AsString := 'Master' + IntToStr(NextMasterID);
  Inc(NextMasterID);
end;

end.

DFM提取物

object MasterDetailForm: TMasterDetailForm
  OnCreate = FormCreate
  object NavigatorBindSourceDB1: TBindNavigator
    DataSource = BindSourceMaster
  end
  object edMasterID: TEdit
  end
  object edMasterName: TEdit
  end
  object edDetailID: TEdit
  end
  object edDetailMasterID: TEdit
  end
  object edDetailName: TEdit
  end
  object BindNavigator1: TBindNavigator
    DataSource = BindSourceDetail
  end
  object Master: TSimpleDataSet
    Aggregates = <>
    DataSet.MaxBlobSize = -1
    DataSet.Params = <>
    MasterFields = 'MasterID'
    Params = <>
    OnNewRecord = MasterNewRecord
    Left = 64
    Top = 32
    object MasterMasterID: TIntegerField
      FieldName = 'MasterID'
    end
    object MasterName: TStringField
      DisplayWidth = 30
      FieldName = 'Name'
      Size = 30
    end
  end
  object Detail: TSimpleDataSet
    Aggregates = <>
    DataSet.MaxBlobSize = -1
    DataSet.Params = <>
    FieldDefs = <>
    IndexDefs = <
      item
        Name = 'DetailIndex1'
        Fields = 'MasterID;DetailID'
      end>
    IndexName = 'DetailIndex1'
    MasterFields = 'MasterID'
    MasterSource = DataSource1
    PacketRecords = 0
    Params = <>
    StoreDefs = True
    OnNewRecord = DetailNewRecord
    Left = 64
    Top = 224
    object DetailDetailID: TIntegerField
      FieldName = 'DetailID'
    end
    object DetailMasterID: TIntegerField
      FieldName = 'MasterID'
    end
    object DetailName: TStringField
      DisplayWidth = 30
      FieldName = 'Name'
      Size = 30
    end
  end
  object BindSourceMaster: TBindSourceDB
    DataSource.AutoEdit = False
    DataSet = Master
    ScopeMappings = <>
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    object BindGridLink1: TBindGridLink
      Category = 'Links'
      SourceComponent = Master
      ColumnExpressions = <
        item
          Name = 'Exp1'
          ColumnName = 'IDColumn'
          ColumnIndex = 0
          SourceMemberName = 'ID'
          ControlMemberName = 'IDColumn'
          ParseCellExpressions = <>
          FormatCellExpressions = <>
          FormatColumnExpressions = <>
        end>
      PosControlExpressions = <>
      PosSourceExpressions = <>
      FormatControlExpressions = <>
      ClearControlExpressions = <>
    end
    object LinkControlToField1: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceMaster
      FieldName = 'MasterID'
      Control = edMasterID
      Track = False
    end
    object LinkControlToField2: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceMaster
      FieldName = 'Name'
      Control = edMasterName
      Track = False
    end
    object LinkControlToField3: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceDetail
      FieldName = 'DetailID'
      Control = edDetailID
      Track = False
    end
    object LinkControlToField4: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceDetail
      FieldName = 'MasterID'
      Control = edDetailMasterID
      Track = False
    end
    object LinkControlToField5: TLinkControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceDetail
      FieldName = 'Name'
      Control = edDetailName
      Track = False
    end
  end
  object BindSourceDetail: TBindSourceDB
    DataSet = Detail
    ScopeMappings = <>
  end
  object DataSource1: TDataSource
    DataSet = Master
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.