2

Using Delphi Seattle, I'm trying to get the hang of livebinding in our current project and have created a form with an externally filled TFDMemTable. The memTable is connected to a TGrid and to a TListbox. The grid displays all info like it should, but the listbox stays empty.

What am i doing wrong?

Code (simplified from actual situation, but still showing empty listbox):

    unit Unit1;

    interface

    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Rtti, FireDAC.Stan.Intf,
      FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,
      FireDAC.Stan.StorageBin, Data.Bind.EngExt, Fmx.Bind.DBEngExt, Fmx.Bind.Grid, System.Bindings.Outputs,
      Fmx.Bind.Editors, Data.Bind.Components, Data.Bind.Grid, FMX.ListBox, Data.Bind.DBScope, Data.DB, FireDAC.Comp.DataSet,
      FireDAC.Comp.Client, FMX.Layouts, FMX.Grid, FMX.Types, FMX.Controls, FMX.Controls.Presentation, FMX.StdCtrls,
      FMX.Forms;

    type
      TForm1 = class(TForm)
        fdmAccounts: TFDMemTable;
        fdmAccountscode: TStringField;
        fdmAccountsdesc: TStringField;
        bsAccounts: TBindSourceDB;
        Grid1: TGrid;
        BindingsList1: TBindingsList;
        ListBox1: TListBox;
        LinkGridToDataSourcebsAccounts: TLinkGridToDataSource;
        LinkFillControlToField1: TLinkFillControlToField;
        procedure FormCreate(Sender: TObject);
      private
        FItemlist: TStringlist;
        procedure Refreshlist(Sender: TObject);
        procedure UpdateAccounts(afilter: string);
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.fmx}

    procedure TForm1.UpdateAccounts(aFilter: string);
    var
      s: string;
    begin
      with fdmAccounts do
      begin
        EmptyDataSet;

        for s in FItemList do
        begin
          if aFilter.IsEmpty or s.Contains(aFilter) then
            InsertRecord([s, '']);
        end;
      end;
    end;


    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FItemlist := TStringList.Create;
      FItemlist.Delimiter := ',';
      Fitemlist.DelimitedText := 'item1, item2, ander item3, laatste item';

      fdmAccounts.Open;
      Refreshlist(nil);
    end;

    procedure TForm1.Refreshlist(Sender: TObject);
    begin
      UpdateAccounts('');
    end;

    end.

Livebinding definitions:

object BindingsList1: TBindingsList
  Methods = <>
  OutputConverters = <>
  Left = 164
  Top = 237
object LinkGridToDataSourcebsAccounts: TLinkGridToDataSource
  Category = 'Quick Bindings'
  DataSource = bsAccounts
  GridControl = Grid1
  Columns = <>
end
object LinkFillControlToField1: TLinkFillControlToField
  Category = 'Quick Bindings'
  Control = ListBox1
  Track = True
  FillDataSource = bsAccounts
  FillDisplayFieldName = 'desc'
  AutoFill = True
  FillExpressions = <>
  FillHeaderExpressions = <>
  FillBreakGroups = <>
end

end

I aslo tried setting the FillExpression of the LinkFillControlToField1 to this:

  FillExpressions = <
    item
      SourceMemberName = 'desc'
      ControlMemberName = 'Text'
    end>

But with the same result .. empty listbox

Bascy
  • 2,017
  • 1
  • 21
  • 46

1 Answers1

2

Update:

Hopefully, if you follow this example, which is from my second attempt at using LiveBindings to populate a ListBox fom a TClientDataSet, you should be able to get it working, too. You might want to note the problem with populating a TStringGrid I mention in the original version of this answer, below.

DFM extract

  object ListBox1: TListBox
    Left = 8
    Top = 320
    Width = 121
    Height = 97
    ItemHeight = 13
    TabOrder = 6
  end
  object DataSource1: TDataSource
    DataSet = CDS1
    Left = 128
    Top = 24
  end
  object CDS1: TClientDataSet
    Aggregates = <>
    Params = <>
    OnNewRecord = CDS1NewRecord
    Left = 72
    Top = 24
    object CDS1ID: TIntegerField
      FieldName = 'ID'
    end
    object CDS1Name: TStringField
      FieldName = 'Name'
      Size = 40
    end
    object CDS1Value: TStringField
      FieldName = 'Value'
      Size = 80
    end
  end
  object BindSourceDB1: TBindSourceDB
    DataSource = DataSource1
    ScopeMappings = <>
    Left = 216
    Top = 32
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 72
    Top = 96
    object LinkListControlToField1: TLinkListControlToField
      Category = 'Quick Bindings'
      DataSource = BindSourceDB1
      FieldName = 'Name'
      Control = ListBox1
      FillExpressions = <>
      FillHeaderExpressions = <>
      FillBreakGroups = <>
    end
  end

Code extract

procedure TForm1.FormCreate(Sender: TObject);
var
  i : Integer;
begin
  CDS1.IndexFieldNames := 'ID';
  CDS1.CreateDataSet;

  for i := 1 to 6 do begin
    CDS1.Insert;
    CDS1.FieldByName('Name').AsString := 'Name  ' + IntToStr(i);;
    CDs1.FieldByName('Value').AsString := 'Value  ' + IntToStr(i);
    CDS1.Post;
  end;

  CDS1.First;
  StringGrid1.Invalidate;
end;

procedure TForm1.CDS1NewRecord(DataSet: TDataSet);
begin
  Inc(NextID);
  DataSet.FieldByName('ID').AsInteger := NextID;
end;

The only thing that's different between this amd my earlier attempt is the

LinkListControlToField1: TLinkListControlToField

I'd assumed (wrongly, it turns out) that a TLinkListControlToField was for TListViews, but it evidently works with TListViews as well

Originally-posted answer

I'm not sure you are doing anything wrong, LiveBindings seem plain buggy to me - see my answer to this q: Delphi TEdit to filter Tstringgrid with Access. The fact that the stringrid shows the row with ID=6 duplicated, but not the one with ID=5 struck me as not particularly promising, seeing as it was such a glaring problem.

I can't get LiveBindings to work with a ListBox either, doing it myself from scratch in a new Seattle VCL project or following this article http://edn.embarcadero.com/article/41707. One of several problems with that article is that it refers to a "TBindScopeDB" component, which is non-existent as far as I can see. Even allowing for the fact that it may be a typo for "TBindSourceDB", I don't get the described results when I try to follow the steps in the article, and the ListBox certainly doesn't get populated.

You might want to take a look at the SourceForge VCL project it mentions, https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist. I haven't tried it myself, but it looks a helluvah lot more complicated than I was expecting, though whether that's because it was for XE2 and LiveBindings have moved on since then, I don't know. I did look at the DFMs and I would never have guessed that the Expression properties would be given the values they are, either from first principles or what it says in the article. I tried using them in my project, but the ListBox stayed empty.

Community
  • 1
  • 1
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Indeed, all documentation and blog posts use the non existing TBindScope, including the svn project you mention. I'll try the TLinkListControlToField suggestion and will report the resuls – Bascy May 20 '16 at 14:33
  • Did this work for you or are you still having a problem? – MartynA May 22 '16 at 14:12
  • No havent been able to get it to work. I've put it on hold for now, and wrote the code to update the comboedit-list manually – Bascy May 23 '16 at 11:24