# Collections

**Structr.Collections** package is intended to help organize search results collections into pagination-friendly arrays, which provide all needed data to display page control buttons in UI. Instance of package main class - `PageList` - contains data about page number, page size, first and last pages of whole selection, etc.

## Installation

Collections package is available on [NuGet](https://www.nuget.org/packages/Structr.Collections/).

```
dotnet add package Structr.Collections
```

## Usage

Let's imagine we have some set of goods gotten from database using search criteria "fruits":

```
{ "apple", "banana", "pear", "orange", "mandarin", "plum", "lime", "mango", "cherimoya", "feijoa", "guava", "lemon", "kumquat" };
```

But for some reason we could show only 3 items from search results per page. So, user will get totally 5 pages and currently will see one of them. Let it be the second one. Than after using all skips and takes in our SQL-query we'll get something like this:

```csharp
var fruits = new List<string> { "orange", "mandarin", "plum" };
```

Before sending this result to presentation level, it will be nice to send some pagination info along with `fruits`-list to provide data you need for user control generation purpose. These are: buttons with page numbers, arrows, total count info. At this moment `PagedList` comes to our help:

```csharp
var result = new PagedList<int>(
     collection: fruits, 
     totalItems: 13, 
     pageNumber: 2, 
     pageSize: 3
);
```

`totalItems` parameter (which is **13**) usually comes from first SQL `COUNT(*)`-like query intended to get total count of elements in search before applying `SKIP` and `TAKE` operators. The second and third parameters here are: `pageNumber` and `pageSize` respectively. Based on such `result` you can successfully create user interface or provide info about search results to you API-client.

## Properties

| Property name   | Property type | Description                                                |
| --------------- | ------------- | ---------------------------------------------------------- |
| TotalItems      | `int`         | Gets declared total count of items in superset collection. |
| PageNumber      | `int`         | Gets current page number.                                  |
| PageSize        | `int`         | Gets page size.                                            |
| TotalPages      | `int`         | Gets total count of pages.                                 |
| HasPreviousPage | `bool`        | Determines if there is a page before current.              |
| HasNextPage     | `bool`        | Determines if there is a page after current.               |
| IsFirstPage     | `bool`        | Determines whether current page is the first one.          |
| IsLastPage      | `bool`        | Determines whether current page is the last one.           |
| FirstItemOnPage | `int`         | Gets number of first item on page.                         |
| LastItemOnPage  | `int`         | Gets number of last item on page.                          |
| Count           | `int`         | Gets count of items on page.                               |

## Static methods

| Method name | Return type    | Description                  |
| ----------- | -------------- | ---------------------------- |
| Empty       | `PagedList<T>` | Creates an empty paged list. |

## Extensions

To easily get a paged list from the original list use extension methods:

```csharp
var list = new List<string> { "orange", "mandarin", "plum" };
// Option 1: Get `PagedList` with total items count equal to size of original collection
var pagedList = list.ToPagedList(pageNumber: 2, pageSize: 3);
// Option 2: Get `PagedList` with total items comes from `COUNT(*)`-like SQL-query
var pagedList = list.ToPagedList(totalItems: 13, pageNumber: 2, pageSize: 3);
```

It is very common to convert an existing paged list of items of one type (Entities for example) into an paged list of items of another type (DTO for example).

```csharp
// Paged list of entities
IPagedEnumerable entities = new PagedList<Fruit>(
     new List<Fruit> {
          new Fruit("orange"),
          new Fruit("mandarin"),
          new Fruit("plum")
     }, 
     totalItems: 13, 
     pageNumber: 2,
     pageSize: 3);
// Paged list of DTO
var dto = entities.ToPagedList(_mapper.Map<FruitDto>(entities));
```

For such conversion it is best to use [AutoMapper extensions](/utilities/collections/automapper-extensions.md).

Use `SerializablePagedList` class with `ToSerializablePagedList()` and `ToPagedList()` methods if you need serialize and deserialize a paged list (to JSON for example):

```csharp
var pagedList = new PagedList<FruitDto>(
     new List<FruitDto> {
          new FruitDto("orange"),
          new FruitDto("mandarin"),
          new FruitDto("plum")
     }, 
     totalItems: 13, 
     pageNumber: 2,
     pageSize: 3);

// Serialize
SerializablePagedList<FruitDto> serializablePagedList = pagedList.ToSerializablePagedList();
string json = JsonSerializer.Serialize(serializablePagedList);

// json:
//{
//  "Items": [
//    { "Name": "orange" },
//    { "Name": "mandarin" },
//    { "Name": "plum" }
//  ],
//  "TotalItems": 13,
//  "PageNumber": 2,
//  "PageSize": 3
//}

// Deserialize
serializablePagedList = JsonSerializer.Deserialize<SerializablePagedList<FruitDto>>(json);
pagedList = serializablePagedList.ToPagedList();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.structr.dev/utilities/collections.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
