0
votes

Using Delphi XE8 I'm currently testing functionality with Firemonkey TListViews.

One thing I'm trying to do is to load a field of all records from a TFDMemtable component into a Listview Item, specifically into the DetailObject of the ListView Item.

For example, I have 3 records in a table (db field is called 'Name'):

Record 1 = Name 1  
Record 2 = Name 2  
Record 3 = Name 3  

There is only 1 DetailObject property per ListView Item so my question is, would I be able to add all of the fields (Name 1, Name 2, Name 3) into that one DetailObject?

Below is what I've attempted so far but no luck. Not 100% sure what I need to do.

procedure MainForm.BuildList;
var LItem : TListViewItem;
begin
  ListView1.BeginUpdate;
  try
    ListView1.CLearItems;
    LItem := ListView1.Items.Add;
    LItem.Objects.DetailObject.Visible := True;
    with memtable do
    begin
      while not eof do
      begin
        LItem.Detail := FieldByName('Name').AsString;
      end;
    end;
  finally
    ListView1.EndUpdate;
  end;
end;

I'm sorry if this isn't clear enough, please let me know.

Any help would be great.

1

1 Answers

1
votes

I think I should warn you that before seeing your q, I'd never done anything with FMX ListViews and Master/Detail datasets. The Following is a little rough around the edges, and the layout isn't ideal, but it shows one way to populate a ListView from Master + Detail datasets. I have no idea whether there are better ways. Personally, I would see if I could use Live Bindings to do the job.

procedure TMasterDetailForm.BuildList;
var
  LItem : TListViewItem;
  DetailItem : TListViewItem;
  ListItemText : TListItemText;
  DetailIndex : Integer;
begin
  ListView1.BeginUpdate;
  ListView1.ItemAppearanceObjects.ItemEditObjects.Text.TextVertAlign := TTextAlign.Leading;  // The default 
  //  seems to be `Center`, whereas we want the Master field name to be at the top of the item

  try
    ListView1.Items.Clear; //Items;
    Master.First;
    while not Master.eof do begin
      LItem := ListView1.Items.Add;
      LItem.Text := Master.FieldByName('Name').AsString;
      LItem.Height := 25;

      Detail.First;
      DetailIndex := 0;
      while not Detail.Eof do begin
        Inc(DetailIndex);
        ListItemText := TListItemText.Create(LItem);
        ListItemText.PlaceOffset.X := 100;
        ListItemText.PlaceOffset.Y := 25 * (DetailIndex - 1);
        ListItemText.TextAlign := TTextAlign.Leading;
        ListItemText.Name := 'Name' + IntToStr(DetailIndex); //Detail.FieldByName('Name').AsString;
        LItem.Data['Name' + IntToStr(DetailIndex)] := Detail.FieldByName('Name').AsString;
        Detail.Next;
      end;
      LItem.Height := LItem.Height * (1 + DetailIndex);

      Master.Next;
    end;
  finally
    ListView1.EndUpdate;
  end;
end;

TListItemText is one of a number of "drawable" FMX objects that can be added to do the TListViewItem. They seem to need unique names so that they can be accessed via the Names property.

FWIW, I used 2 TClientDataSets as the Master and Detail in my code.

Also FWIW, for FMX newbies like me, populating an FMX TreeView is a lot more like what you'd do in a VCL project:

procedure TMasterDetailForm.BuildTree;
var
  PNode,
  ChildNode : TTreeViewItem;
begin
  TreeView1.BeginUpdate;
  try
    TreeView1.Clear;
    Master.First;
    while not Master.eof do begin
      PNode := TTreeViewItem.Create(TreeView1);
      TreeView1.AddObject(PNode);
      PNode.Text := Master.FieldByName('Name').AsString;

      Detail.First;
      while not Detail.Eof do begin
        ChildNode := TTreeViewItem.Create(TreeView1);
        ChildNode.Text := Detail.FieldByName('Name').AsString;
        PNode.AddObject(ChildNode);
        Detail.Next;
      end;
      Master.Next;
    end;
  finally
    TreeView1.EndUpdate;
  end;
end;

Btw, in your code you should have been calling

memtable.Next;

in your while not eof loop, and memtable.First immediately before the loop.