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

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

_________________________________
ФИО1
Страна1
ФИО2
Страна2
ФИО3
Страна3
и т.д...

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;

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

введите здесь описание изображения


person Rafik Bari    schedule 23.12.2011    source источник
comment
Вы добавляете элементы, а не подэлементы! Вам нужно добавить элемент, а затем с этим возвращаемым значением добавить в коллекцию SubItems.   -  person Lloyd    schedule 23.12.2011
comment
Помимо использования подэлементов, вы, вероятно, захотите установить свойство Visible ListView вне цикла...   -  person Marjan Venema    schedule 23.12.2011
comment
Перейдите к этому ТАК-вопросу.   -  person menjaraz    schedule 23.12.2011
comment
Знаете ли вы, что могли бы просто использовать DBGrid и позволить delphi сделать всю работу за вас. Это называется Data Aware Controls, и это очень хорошая возможность в Delphi. Вы можете сделать это без какого-либо кода, часто.   -  person Warren P    schedule 23.12.2011


Ответы (4)


Во-первых: добавьте заголовки столбцов:

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;

Обновлять:

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

person Marjan Venema    schedule 23.12.2011
comment
Я подозреваю, что ViewStyle также нужно установить на vsReport. - person David Heffernan; 23.12.2011
comment
Ваш код не работает, он не содержит ошибки, но когда я нажимаю кнопку, которая должна открыть окно, содержащее список, ничего не происходит!:! - person Rafik Bari; 23.12.2011
comment
@DavidHeffernan: Да, я предполагал, что OP уже понял это. Может быть нет. - person Marjan Venema; 23.12.2011
comment
@RafikBari Этот код скопирован из рабочего примера и отредактирован только для того, чтобы разрешить использование ваших имен столбцов и запросов. Это не работает, не помогает мне помочь вам. Вам нужно будет предоставить гораздо больше информации и, возможно, ваш измененный код (отредактируйте свой вопрос), чтобы кто-нибудь мог вам эффективно помочь. - person Marjan Venema; 23.12.2011
comment
@Rafik Ты хотел сказать, что я не могу заставить твой код работать в моем приложении. Этот код просто отлично. Я предполагаю, что вы не установили ViewStyle, но может быть много других причин. - person David Heffernan; 23.12.2011
comment
@DavidHeffernan: спасибо. Или он удалил ListView1.Visible := True; вместо того, чтобы переместить его за пределы цикла. - person Marjan Venema; 23.12.2011
comment
УПС § Извините! Код работает нормально, спасибо, кажется, в моем проекте была другая часть кода, которая вызывает ошибку, теперь все работает нормально. Спасибо вам всем - person Rafik Bari; 23.12.2011

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

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, чтобы отображать список в виде сетки.

person kludg    schedule 23.12.2011

Я не уверен, как сделать список многострочным, но я знаю, что вы неправильно используете запрос. В нынешнем виде ваш код имеет дыру для 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;
person Johan    schedule 23.12.2011

Документация 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.

person David Heffernan    schedule 23.12.2011
comment
Я не знал, что примеры были на sourceforge. Хорошо на них. - person Marjan Venema; 23.12.2011
comment
@Marjan Marjan Я тоже не знал, пока не погуглил, чтобы найти этот ответ. - person David Heffernan; 23.12.2011