3
votes

Im having a lot of trouble trying to create a customized item appearance for the TListView firemonkey control for Delphi XE7. What I want is to define my own "design" for what an item should be and use that item. For example :

I would like to have an item with a Title(on top) - A Description(Middle) - A Date (Bottom) - Button(Right).

I could not find any good documentation about this but i got some samples of how to create an TListView with muti details, but the problem is : that sample is not documented so is very hard to understand whats going on there.

I would like to have a link or some explanation of how to do this, or if theres other way to achive what I want. I have tried using TListBox but the performance on mobile is a little bad. I have to say that I could make what I want with TListBox, but this is the problem... The performance.

So I would like to have a control to list items(that I can create by my own) with a good performance.

1
Are you looking over the samples found here? C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\Mobile Samples\User Interface\ListView Andrea Magni also has a blog post about this here:blog.delphiedintorni.it/2014/05/…SmeTheWiz
Yes, those were the samples I've seen, but unfortunately I could not understand because it is not very documented.gugamm
It's sort of involved since you have to add your custom controls and offsets programmatically first in the package. Once you do that you install it, and can select it from the design options on the listview. I know you said you already tried a listbox, but what specifically is the performance problem you were having with it? Personally I would try to use the listbox instead with custom styled listbox items.SmeTheWiz
Basically what i want is to create a custom ui and use it as a scrolling list. The problem is that if i add a lot of items in a scrollbox or in a listbox, they will not scroll smoothly as i want(even if i use background threads to deal with hard code). I would like to use a custom ui inside of a listview because i think that the performance would be better, or a solution in case i want to display custom uis with a scroll with a good performance.gugamm
There are very important reasons why to use one over the other. TListBox is meant when each item may contain different contents (such as a settings screen), and not too many items. TListView is meant for a large list of same-type items, such as search results - where all items look the same. Anyway, I've heard of third-party libraries which allow you to design a TListView, however I choose to write pure code for this.Jerry Dodge

1 Answers

5
votes

A TListView is indeed the appropriate thing to use when you have many items which are to have the same layout as each other (although it is possible to make each one vary from the next). A TListBox is only meant when you have not too many items, and each one needs to have different contents (such as configuring application settings). I actually just got done fixing this mistake, switching some List Boxes to List Views.

The tools built-in to Delphi don't necessarily allow you to design a layout / template in design-time (I've heard of third-party libraries for this), however you can still customize it with code. A TListView does not actually contain controls inside - instead a particular type of object (inherited from TListItemObject). These are virtual objects meant to place various types of data in the final drawing.

This starts by adding an event handler for TListView.OnUpdateObjects. This is where you essentially "design" the layout. Here's some code which I'm using for example in some inventory search results:

procedure TfrmInventoryContent.lstItemsUpdateObjects(const Sender: TObject; const AItem: TListViewItem);
var
  TextLabel: TListItemText;
begin
  //Add objects per item in list view for displaying more info

  //Item Price Label
  TextLabel := AItem.Objects.FindObject('lblPrice') as TListItemText;
  if TextLabel = nil then begin
    TextLabel:= TListItemText.Create(AItem);
    TextLabel.Name:= 'lblPrice';
    TextLabel.Align:= TListItemAlign.Trailing;
    TextLabel.VertAlign:= TListItemAlign.Leading;
    TextLabel.TextAlign:= TTextAlign.Trailing;
    TextLabel.PlaceOffset.X:= -10;
    TextLabel.PlaceOffset.Y:= 4;
    TextLabel.Font.Size:= 14;
    TextLabel.Width:= 60;
    TextLabel.Height:= 18;
    TextLabel.Text:= '';
    TextLabel.TextColor:= TAlphaColorRec.Green;
  end;
  //Item Quantity Label
  TextLabel := AItem.Objects.FindObject('lblQty') as TListItemText;
  if TextLabel = nil then begin
    TextLabel:= TListItemText.Create(AItem);
    TextLabel.Name:= 'lblQty';
    TextLabel.Align:= TListItemAlign.Trailing;
    TextLabel.VertAlign:= TListItemAlign.Leading;
    TextLabel.TextAlign:= TTextAlign.Trailing;
    TextLabel.PlaceOffset.X:= -120;
    TextLabel.PlaceOffset.Y:= 4;
    TextLabel.Font.Size:= 14;
    TextLabel.Width:= 30;
    TextLabel.Height:= 18;
    TextLabel.Text:= '';
    TextLabel.TextColor:= TAlphaColorRec.Blue;
  end;
end;

There are other similar types other than just TListItemText, inheriting from TListItemObject. You can even design your own if you need to. Once you have designed this layout, you then need to populate the contents...

var
  TextLabel: TListItemText;
  I: TListViewItem;
begin
  //Assuming I is already added to list somewhere
  TextLabel := I.Objects.FindObject('lblPrice') as TListItemText;
  if Assigned(TextLabel) then begin
    TextLabel.Text:= FormatFloat('$#,##0.00', InventoryItem.CustomerPrice.Price);
  end;

  TextLabel := I.Objects.FindObject('lblQty') as TListItemText;
  if Assigned(TextLabel) then begin
    TextLabel.Text:= IntToStr(InventoryItem.Quantity);
  end;
end;

Note how each of these objects has a "name" which is to be unique (but doesn't follow the same component names you're already used to). These names are unique to each list item.