Как правильно использовать Listview в Delphi?

Мой код ниже, он работает правильно, но, после компиляции программы, я вижу все полное имя и страну, перечисленные по вертикали, что-то вроде:

_________________________________
Fullname1
стране1
Fullname2
COUNTRY2
Fullname3
COUNTRY3
так далее...

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;

Но я хочу что-то вроде:

5 ответов

Решение

Сначала: добавьте заголовки столбцов:

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;

затем добавьте записи следующим образом:

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;

Обновить:

Конечно, чтобы получить список, как на скриншоте, вам нужно установить ListView ViewStyle собственность на vsReport

Ваш код должен выглядеть так:

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;

Вы также должны установить ListView.Style в vsReport показать список в виде сетки.

Я не уверен, как сделать просмотр списка многострочным, но я точно знаю, что вы не используете запрос правильно. В вашем коде есть дыра для SQL-инъекций, и неявная ссылка на 'fieldbyname' внутри цикла делает его медленным.

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;

Документация Delphi содержит этот пример, который делает именно то, что вы хотите.

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;

Несмотря на то, что документация Delphi очень злонамеренна, она часто содержит очень полезные примеры, подобные этому. Страница шлюза к примерам находится здесь, и примеры даже доступны на sourceforge, так что вы можете проверить их, используя ваш любимый клиент SVN.

Procedure TForm1.GetUsers;
var
  ListItem: TListItem;
begin
  try
    ListView1.Items.BeginUpdate;
    try
      ListView1.Clear;
      MySQLQuery.SQL.Clear;
      MySQLQuery.SQL.Add('select * from users;');
      MySQLQuery.Open;
      while (not MySQLQuery.EOF) do
      begin
        ListItem := ListView1.Items.Add;
        ListItem.Caption:= VarToSTr(MySQLQuery['username']);
        with ListItem.SubItems do
          begin
            Add(VarToSTr(MySQLQuery['password']));
            Add(VarToSTr(MySQLQuery['maxscore']));
          end;
        MySQLQuery.Next;
      end;
      MySQLQuery.Close;
    finally
      ListView1.Items.EndUpdate;
    end;
  except
    on E: Exception do
        MessageDlg(PWideChar(E.Message), TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
  end;
end;
Другие вопросы по тегам