Delphi XE8 TBindSourceDB компонент с использованием MasterSource - PullRequest
0 голосов
/ 22 апреля 2020

Вопрос в том, как правильно использовать MasterSource для TBindSourceDB Ex.

1 ListView с отделами с навигатором, связанным с TBindSourceDB (мастер). Когда нажата кнопка «Навигатор», активируется другой вид списка, список городов. Теперь ListView городов с другим навигатором связывается с другим TBindSourceDB, городами (подробности). Мне нужно, чтобы города были переведены в департаменты. Как и где это должно быть сделано?

И главный, и подробный TBindSourceDB связаны с компонентами Fireda c TSimpleDataSet, которые имеют свойство MasterSource. Я заполнил это свойство подробно, указывая на главный компонент. Проблема заключается в следующем: когда нажата вставка кнопки «подробности», запускается OnBeforePost из TSimpleDataSet, потому что он хочет сделать публикацию !! и не запускает событие OnAfterInsert. Каков правильный режим для работы master-> detail data с компонентами Firemonkey и TBindSourceDB?.

1 Ответ

0 голосов
/ 23 апреля 2020

Если я правильно понимаю, что вы спрашиваете, я думаю, что проект ниже покажет вам самые важные вещи о добавлении записей Master + Detail. Я думаю, что TListViews на самом деле отвлекают от понимания того, что необходимо, поэтому я собираюсь пропустить их и вместо этого использовать некоторые TEdits для отображения записей Master + Details по очереди.

По моему опыту Основное правило - избегать использования чего-либо с использованием LiveBindings, если есть более простой способ сделать это, и это тот случай, когда речь идет об установлении отношения Master-> Detail между Master и Details.

Итак, среди списка компонентов в форме есть TDataSource, который связывает их. Его свойство DataSet связано с мастером; на стороне детализации свойство MasterSource детализации должно быть установлено на него, а его свойство MasterField установлено в поле MasterID мастера.

Смысл добавления TDataSource заключается в том, что он позволяет использовать стандартную модель TDataset и события он поддерживает выполнение всей работы, необходимой для установления связи между новой записью сведений при ее вставке и текущей MasterRecord. Это делается в событии OnNewRecord объекта Detail, которое выглядит следующим образом:

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 заключается в том, что он гарантирует правильную синхронизацию мастера и детали при вставке новой записи детали. .

Единственный другой код подписи находится в 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
...