Search code examples
androidiosdelphifiremonkeydelphi-xe8

Build TListView programmatically not using livebindings


I have a cross platform app which contains a TFDMemtable(FireDAC).

My question is, how would one manually build a TListView from the records in this table?

The table I have contains a list of male forenames in alphabetical order.

e.g. Adam, Anthony, Alan, Brian, Bill, Bob, Ben, Charlie, Craig, Christopher, Colin and so on.

I want the listview to include groupings for the names, so A,B,C etc.

I have the following so far:

procedure BuildNameList;
var Litem : TListViewItem;
c : Char;
begin
  ListView1.BeginUpdate;
  try
   ListView1.ClearItems;

  for c := 'A' to 'Z' do
  begin
    with ListView1.Items.Add do
    begin
      Text := char(c);
      Purpose := TListItemPurpose.Header;
    end;

  with dmod.tableNames do
  begin
    First;
   while not Eof do
    begin
      Litem := ListView1.Items.Add;         
      Litem.Text := dmod.tableNames.FieldByName('ForeName').AsString;
      Next;
    end;
  end;
  end;
  finally
    ListView1.EndUpdate;
end;

The above code doesn't give me the result I'm after, what happens is I get every name duplicated under every letter group(A-Z).

Any suggestions/help would be much appreciated. Thanks


Solution

  • You need to change your logic somewhat to add first the header, and then the names under that header, and then the next header and set of names. Here's a full test app that demonstrates. You'll need to drop a FMX TListView and a TClientDataSet on your form and connect up the FormCreate event to see it work. (Note that the index is needed on the ClientDataSet in order to ensure the names are in the proper order; if they're not alphabetized, the code won't work, because it won't find the data as needed to add to the section.)

    unit Unit3;
    
    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.DB,
      Datasnap.DBClient, FMX.ListView;
    
    type
      TForm3 = class(TForm)
        ListView1: TListView;
        CDS: TClientDataSet;
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        procedure BuildNameList;
      public
        { Public declarations }
      end;
    
    var
      Form3: TForm3;
    
    implementation
    
    {$R *.fmx}
    
    procedure TForm3.BuildNameList;
    var
      Item: TListViewItem;
      Ch: Char;
    begin
      ListView1.BeginUpdate;
      CDS.First;
      try
        ListView1.ClearItems;
        for Ch := 'A' to 'Z' do
        begin
          Item := ListView1.Items.Add;
          Item.Text := Ch;
          Item.Purpose := TListItemPurpose.Header;
    
          while (CDS.FieldByName('SurName').AsString[1] = Ch) and (not CDS.Eof) do
          begin
            Item := ListView1.Items.Add;
            Item.Text := CDS.FieldByName('SurName').AsString + ', ' +
                         CDS.FieldByName('ForeName').AsString;
    
            CDS.Next;
          end;
        end;
      finally
        ListView1.EndUpdate;
      end;
    end;
    
    procedure TForm3.FormCreate(Sender: TObject);
    begin
      // Create some test data
      CDS.FieldDefs.Add('ForeName', ftString, 20);
      CDS.FieldDefs.Add('SurName', ftString, 30);
      CDS.CreateDataSet;
      CDS.Open;
      CDS.AppendRecord(['John', 'Smith']);
      CDS.AppendRecord(['Jane', 'Doe']);
      CDS.AppendRecord(['Ralph', 'Richards']);
      CDS.AppendRecord(['Fred', 'Fredericks']);
      CDS.AppendRecord(['Sam', 'Samuels']);
      CDS.AppendRecord(['Walter', 'Williams']);
      CDS.AppendRecord(['Ann', 'Anderson']);
      CDS.AppendRecord(['Bob', 'Barnes']);
    
      // Index it to put it in alphabetical order
      CDS.IndexDefs.Add('Names', 'SurName;ForeName', []);
      CDS.IndexName := 'Names';
      BuildNameList;
    end;
    
    end.
    

    Here's a screenshot of a center section of that sample app's ListView, so you can see the results:

    ListView displaying alpha list with section headers