90 votes

Paging d'une collection avec LINQ

Comment feuilletez-vous une collection dans LINQ étant donné que vous avez un startIndex et un count ?

65voto

Nick Berardi Points 31361

C'est très simple avec les méthodes d'extension Skip et Take .

 var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);
 

46voto

Wolfbyte Points 11270

Il y a quelques mois, j'ai écrit un article sur les interfaces Fluent et LINQ, qui utilisait une méthode d'extension sur IQueryable<T> et une autre classe pour fournir le moyen naturel suivant de paginer une collection LINQ.

 var query = from i in ideas
            select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);
 

Vous pouvez obtenir le code à partir de la page Galerie de codes MSDN: Pipelines, Filtres, API Fluent et LINQ to SQL .

15voto

Spoike Points 32082

J'ai résolu ce problème un peu différemment de ce que les autres ont comme j'ai eu à faire mon propre paginator, avec un répéteur. J'ai donc d'abord fait une collection de numéros de page pour la collecte des éléments que j'ai:

// assumes that the item collection is "myItems"

int pageCount = (myItems.Count + PageSize - 1) / PageSize;

IEnumerable<int> pageRange = Enumerable.Range(1, pageCount);
   // pageRange contains [1, 2, ... , pageCount]

À l'aide de ce que je pouvais facilement la partition de la collection d'éléments dans une collection de "pages". Une page dans ce cas est simplement une collection d'objets (IEnumerable<Item>). C'est comment vous pouvez le faire en utilisant Skip et Take ensemble avec la sélection de l'indice de l' pageRange créé ci-dessus:

IEnumerable<IEnumerable<Item>> pageRange
    .Select((page, index) => 
        myItems
            .Skip(index*PageSize)
            .Take(PageSize));

Bien sûr, vous avez à gérer chaque page est une collection mais par exemple, si vous êtes à la nidification des répéteurs puis c'est facile à gérer.


Le one-liner TLDR version serait celui-ci:

var pages = Enumerable
    .Range(0, pageCount)
    .Select((index) => myItems.Skip(index*PageSize).Take(PageSize));

Qui peut être utilisé comme ceci:

for (Enumerable<Item> page : pages) 
{
    // handle page

    for (Item item : page) 
    {
        // handle item in page
    }
}

11voto

Nico Points 667

Cette question est un peu ancienne, mais je voulais publier mon algorithme de pagination qui montre toute la procédure (y compris l'interaction de l'utilisateur). Il stocke également le " décalage de la dernière page " au lieu de passer de plus en plus d'éléments identiques, ce qui serait quelque peu inefficace.

 const int pageSize = 10;
const int count = 100;
const int startIndex = 20;

int took = 0;
bool getNextPage;
var page = ideas.Skip(startIndex);
do
{
    Console.WriteLine("Page {0}:", (took / pageSize) + 1);
    foreach (var idea in page.Take(pageSize))
    {
        Console.WriteLine(idea);
    }

    took += pageSize;
    Console.WriteLine("Next page (y/n)?");
    char answer = Console.ReadLine().FirstOrDefault();
    getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);
    if (getNextPage)
    {
        page = page.Skip(pageSize);
    }
}
while (getNextPage && took < count);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X