Публикации Lazarus

ListView и разбиение данных на порции (ч.2)

27.07.2009
Leonardo M. Rame
Leonardo M. Rame
Кордоба, Аргентина
Источник - Leonardo's blog
Перевод и переделка примера под FreePascal+Lazarus - Вадим Исаев

Привязка TCollections к разбиению данных на порции в ListView

В предыдущей части статьи я написал о методе разбиения данных на порции, которые отображаются в ListView. Теперь я хочу расширить метод, заменяя TDataSet на TCollection.

Что такое TCollection?

TCollection - контейнер, где сохраняются объекты только одного типа. В отличие от других контейнеров, таких как TList и TObjectList, которые могут содержать любой вид - указателя, в случае TList, и разнородных объектов в случаеTObjectList, в TCollection могут использоваться только объекты определенного класса.

Коллекция Песен

Чтобы создать коллекцию Песен, мы должны унаследовать класс из TCollectionItem, назовём например TSong и другой класс от TCollection, например TSongs, следующим образом:

TSong = class(TCollectionItem)
private
  FId: string;
  FSolist: string;
  FSongName: string;
public
  property Id: string read FId write FId;
  property Solist: string read FSolist write FSolist;
  property SongName: string read FSongName write FSongName;
end;
 
TSongs = class(TCollection)
private
  function GetItem (AIndex: Integer): TSong;
public
  function Add: TSong;
  property Items[AIndex: Integer]: TSong read GetItem; default;
end;

Теперь определяем методы Add и GetItem:

function TSongs.GetItem (AIndex: Integer): TCustomer;
begin
  Result: = TSongs(inherited GetItem(AIndex));
end;
 
function TSongs.Add: TCustomer;
begin
  Result: = TSongs(inherited Add);
end;

Сохраните вышеупомянутый код в модуле c названем songs.pas, затем создайте новое приложение и добавьте названте недавно созданного модуля в раздел "Uses" основной формы, затем добавьте свойство FSongs: TSongs; в private секцию формы:

type
TForm1 = class(TForm)
private
  FSongs: TSongs;
public
  {Public declarations}
end;

Теперь измените методы OnCreate и OnDestroy основной формы, чтобы создавать и удалять коллекцию:

procedure TForm1.FormCreate(Sender: TObject);
begin
  FSongs: = TSongs.Create(TSong);
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  FSongs.Free;
end;

От набора данных к коллекции

Итак, следующи шагом заполняем коллекцию данными.

Поместите компоненты обеспечения связи с базой данных так же, как я объяснял в предыдущей части статьи, в DataModule или в основной форме (т.к. это - только пример).

Далее доработаем метод FormCreate вот так:

procedure TForm1. FormCreate (Sender: TObject);
begin
  //Создаем коллекцию
  FSongs:=TSongs.Create(TSong);

  //Определяем общее количество записей
  SQLQuery1.SQL.Clear;
  SQLQuery1.SQL.Text:='SELECT COUNT(*) FROM rus';
  SQLQuery1.Open;
  FAllRecords:=SQLQuery1.Fields[0].AsInteger;
  SQLQuery1.Close;

  //Основной запрос
  SQLQuery1.SQL.Clear;
  SQLQuery1.SQL.Add('SELECT rus.id, sol.name, rus.name');
  SQLQuery1.SQL.Add('FROM rus INNER JOIN sol');
  SQLQuery1.SQL.Add('ON rus.sol_id=sol.id');
  SQLQuery1.SQL.Add('ORDER BY sol.name, rus.name');
  SQLQuery1.SQL.Add('LIMIT '+IntToStr(cPageSize)+' OFFSET :n');

  SQLQuery1.Params[0].AsInteger:=0;
  SQLQuery1.Open;
  GetCurrentPage(dqCurr);
end;

Теперь, чтобы заполнить наш TCollection данными из базы данных, измените метод GetCurrentPage таким образом:

procedure TForm1.GetCurrentPage(Dir: TDirQuery);
Var
  i: Integer;
begin
  //В зависимости от параметра процедуры определяем с какого номера записи проводить выборку
  Case Dir of
    dqPrev: If SQLQuery1.Params[0].AsInteger>=cPageSize Then
              SQLQuery1.Params[0].AsInteger:=SQLQuery1.Params[0].AsInteger-cPageSize;
    dqNext: If SQLQuery1.Params[0].AsInteger<=FAllRecords-cPageSize Then
              SQLQuery1.Params[0].AsInteger:=SQLQuery1.Params[0].AsInteger+cPageSize;
  End;

  SQLQuery1.Close;
  SQLQuery1.Open;

  //Заполняем коллекцию
  FSongs.Clear;
  While not SQLQuery1.Eof Do
  Begin
    With FSongs.Add Do
    Begin
      Id := SQLQuery1.Fields[0].AsString;
      Solist := SQLQuery1.Fields[1].AsString;
      SongName := SQLQuery1.Fields[2].AsString;
    End;
    SQLQuery1.Next;
 End;

  //Заполняем полученой порцией данных компонент отображения
  ListView1.Items.Clear;
  For i:=0 To FSongs.Count-1 Do
  Begin
    ListView1.Items.Add;
    ListView1.Items[i].Caption:=FSongs[i].Id;
    ListView1.Items[i].SubItems.Add(FSongs[i].Solist);
    ListView1.Items[i].SubItems.Add(FSongs[i].SongName);
  End;
end;

Последний шаг - поместите TListView на форму, установите ее свойства как показано в предыдущей части статьи.

Вот и все.

Пример 2: listview2.s3.7z

Актуальные версии
FPC3.2.2release
Lazarus3.2release
MSE5.10.0release
fpGUI1.4.1release
links