How to use Listview correctly in delphi?

52,784

Solution 1

First: add the column headers:

var
  Col: TListColumn;
begin
  Col := ListView1.Columns.Add;
  Col.Caption := 'Name';
  Col.Alignment := taLeftJustify;
  Col.Width := 140;

  Col := ListView1.Columns.Add;
  Col.Caption := 'Country';
  Col.Alignment := taLeftJustify;
  Col.Width := 140;
end;

then add the records as follows:

var
  Itm: TListItem;
begin
    // start of your query loop
    Itm := ListView1.Items.Add;
    Itm.Caption := SQLQuery1['fullname'];
    Itm.SubItems.Add(SQLQuery1['cntry']);
    // end of your query loop
end;

Update:

Of course, in order to get the list as in your screenshot, you need to set the ListView's ViewStyle property to vsReport

Solution 2

Your code should look like that:

var
  ListItem: TListItem;

  ...

  ListView.Items.BeginUpdate;
  try
    while(not SQLQuery1.EOF)do begin
      ListItem:= ListView.Items.Add;
      ListItem.Caption:= 'Full name: '+SQLQuery1['fullname'];
      with ListItem.SubItems do begin
        Add('Country: '+SQLQuery1['cntry']);
// if you need more columns, add here
      end;
      SQLQuery1.Next;
    end;
  finally
    ListView.Items.EndUpdate;
  end;

You should also set ListView.Style to vsReport to show listview as grid.

Solution 3

I'm not sure how to get the listview to multiline, but I do know you're not using the Query correctly. As it stands your code has an SQL-injection hole and the implicit reference to 'fieldbyname' inside the loop makes it slow.

var
  FullName: TField;
  Country: TField;
  ListItem: TListItem;
begin
  //Use Params or suffer SQL-injections
  SQLQuery1.SQL.Text := 'SELECT * FROM users where user_age= :age';
  SQLQuery1.ParamByName('age').AsInteger:= age;
  SQLQuery1.Open;
  if SQLQuery1.RecordCount = 0 then Exit;
  //Never use `FieldByName` inside a loop, it's slow.
  FullName:= SQLQuery1.FieldByName('fullname');
  Country:= SQLQuery1.FieldByName('cntry');
  ListView1.Style:= vsReport;

  SQLQuery1.First; // move to the first record
  SQLQuery1.DisableControls; //Disable UI updating until where done.
  try
    ListView1.Items.BeginUpdate;
    //ListView1.Visible := false;
    while (not SQLQuery1.EOF) do begin
      //Code borrowed from @Serg
      ListItem:= ListView.Items.Add;
      ListItem.Caption:= 'Full name: '+Fullname.AsString;
      ListItem.SubItems.Add('Country: '+Country.AsString);
      SQLQuery1.Next;  
    end; {while}
  finally
    SQLQuery1.EnableControls;
    ListView1.Items.EndUpdate;
  end;
end;

Solution 4

The Delphi documentation contains this example that does exactly what you want.

procedure TForm1.FormCreate(Sender: TObject);
const
  Names: array[0..5, 0..1] of string = (
    ('Rubble', 'Barney'),
    ('Michael', 'Johnson'),
    ('Bunny', 'Bugs'),
    ('Silver', 'HiHo'),
    ('Simpson', 'Bart'),
    ('Squirrel', 'Rocky')
    );

var
  I: Integer;
  NewColumn: TListColumn;
  ListItem: TListItem;
  ListView: TListView;
begin
  ListView := TListView.Create(Self);
  with ListView do
  begin
    Parent := Self;
    Align := alClient;
    ViewStyle := vsReport;

    NewColumn := Columns.Add;
    NewColumn.Caption := 'Last';
    NewColumn := Columns.Add;
    NewColumn.Caption := 'First';

    for I := Low(Names) to High(Names) do
    begin
      ListItem := Items.Add;
      ListItem.Caption := Names[I][0];
      ListItem.SubItems.Add(Names[I][2]);
    end;
  end;
end;

For all that the Delphi documentation is much maligned, it often has very useful examples like this. The gateway page to the examples is here and the examples are even available on sourceforge so you can check them out using your favourite svn client.

Share:
52,784
Rafik Bari
Author by

Rafik Bari

StackOverflow is very amazing *)

Updated on January 19, 2020

Comments

  • Rafik Bari
    Rafik Bari over 4 years

    My code is the below, it's working correctly but, but after compiling program i see all the fullname and country listed vertically something like :

    _________________________________
    Fullname1
    Country1
    Fullname2
    Country2
    Fullname3
    Country3
    etc...

    SQLQuery1.SQL.Text := 'SELECT * FROM users where user_age="'+age+'"';
    SQLQuery1.Open;
    rec := SQLQuery1.RecordCount;
    
    SQLQuery1.First; // move to the first record
    ListView1.Visible := false;
    if rec>0 then
    begin
    while(not SQLQuery1.EOF)do begin
    ListView1.Visible := true;
            // do something with the current item
    ListView1.AddItem('Full name: '+SQLQuery1['fullname'], Self);
    ListView1.AddItem('Country: '+SQLQuery1['cntry'], Self);
    
        // move to the next record
    
    SQLQuery1.Next;
    
    end;
    

    But i want something Like :

    enter image description here

    • Lloyd
      Lloyd over 12 years
      You are adding items and not sub items! You need to add the item and then with that return value add to the SubItems collection.
    • Marjan Venema
      Marjan Venema over 12 years
      Apart from using subitems, you probably want to set the ListView's Visible property OUTside the loop...
    • menjaraz
      menjaraz over 12 years
      Head to this SO question.
    • Warren  P
      Warren P over 12 years
      Are you aware you could have just used a DBGrid and let delphi do the work for you. It's called Data Aware Controls and it's a very nice capability in Delphi. You can do it without any code, often.
  • David Heffernan
    David Heffernan over 12 years
    I suspect that ViewStyle needs to be set to vsReport also.
  • Rafik Bari
    Rafik Bari over 12 years
    Your code doesn't work, it doesn't contain error but when i click on the button that should open the window which contain the listview, nothing happens !:!
  • Marjan Venema
    Marjan Venema over 12 years
    @DavidHeffernan: Yes, I assumed OP had already figured that out. Maybe not.
  • Marjan Venema
    Marjan Venema over 12 years
    @RafikBari This code is copied from a working example and edited only to allow for your column names and query use. "It doesn't work" doesn't help me in helping you. You will have to provide a lot more information and probably your amended code (edit your question) for anybody to be able to help you effectively.
  • David Heffernan
    David Heffernan over 12 years
    @Rafik What you meant to say was "I can't get your code to work in my app". This code is just fine. My guess is you didn't set ViewStyle, but there could be lots of other reasons.
  • Marjan Venema
    Marjan Venema over 12 years
    @DavidHeffernan: thanks. That, or he removed the ListView1.Visible := True; instead of moving it outside of the loop.
  • Rafik Bari
    Rafik Bari over 12 years
    OUPS § Sorry ! The code work fine thankyou it seem there was another part of code in my project that is causing the error, now everything works fine. Thankyou to you all
  • Marjan Venema
    Marjan Venema over 12 years
    I didn't know the examples were on sourceforge. Good on them.
  • David Heffernan
    David Heffernan over 12 years
    @Marjan Neither did I until I googled to come up with this answer.