I have a code that displays pagination on the page:

enter image description here

This displays all the elements as is - from the first to the MaxPage:

@if (Model.IsFirst()) { <li class="page-item disabled"><a class="page-link" href="@Model.GetUrl(1)"><<</a></li> <li class="page-item disabled"><a class="page-link" href="@Model.GetUrl(Model.PageNumber - 1)"><</a></li> } else { <li class="page-item"><a class="page-link" href="@Model.GetUrl(1)"><<</a></li> <li class="page-item"><a class="page-link" href="@Model.GetUrl(Model.PageNumber - 1)"><</a></li> } @for (var i = 1; i <= Model.MaxPageCount; i++) { if (Model.IsCurrent(i)) { <li class="page-item active"> <a class="page-link disabled" href="@Model.GetUrl(i)">@i</a> </li> } else { <li class="page-item"> <a class="page-link" href="@Model.GetUrl(i)">@i</a> </li> } } 

Problems begin when the number of pages becomes more than 10 (and quite often in pagination and on three hundred pages happens) - they fly away for the right border of the screen.

I sit think what condition you need to take to pagination was shown beautifully.

Let's try to formalize the condition. There is some IEnumerable<int> from 1 to Model.MaxPageCount and there is some number PageNumber (current page number) that belongs to this sequence.

Not sure exactly, but let's say I need to get no more than five elements BEFORE the current page and no more than five elements AFTER the current page.

At the same time, I don’t know how to handle the situation nicely, that if there are not enough pages (for example, we are looking at page 3, then there will be pages 1 and 2), then afterwards you probably should take a little more - not five, but three more. But also not the fact that AFTER the necessary number of pages suffices.

The question is rather a beautiful and simple algorithm (how is it usually done in typical paginators?), It is possible that I will write a specific formula myself. If someone has started with a similar task and knows how to do this, offer an option. I looked at various XPagedList options on github, but I didn’t find any convenient options.

  • one
    Look here at RecalcList : ru.stackoverflow.com/a/616413/218063 - Andrey NOP
  • @AndreyNOP wow, this is the answer so responsible. Immediately by Krol bored with such an answer) - tym32167
  • @ tym32167, aha and pagination there is quite worthy - Andrey NOP
  • An excellent answer, and the most interesting thing is that I have my upvout, which means that I have already seen it once)) I did it by analogy. - AK ♦

2 answers 2

Something like that?

 List<int> GeneratePages(int currentPage, int totalPages) { var pages = new List<int>(); for(var i=currentPage; i>0 && i>=currentPage-5; i--) pages.Add(i); pages.Reverse(); for(var i=currentPage+1; i<=totalPages && i<=currentPage+5; i++) pages.Add(i); return pages; } 

Check

 Console.WriteLine( string.Join(",", GeneratePages(50, 100))); Console.WriteLine( string.Join(",", GeneratePages(1, 100))); Console.WriteLine( string.Join(",", GeneratePages(2, 100))); Console.WriteLine( string.Join(",", GeneratePages(98, 100))); Console.WriteLine( string.Join(",", GeneratePages(99, 100))); Console.WriteLine( string.Join(",", GeneratePages(100, 100))); 

results

 45,46,47,48,49,50,51,52,53,54,55 1,2,3,4,5,6 1,2,3,4,5,6,7 93,94,95,96,97,98,99,100 94,95,96,97,98,99,100 95,96,97,98,99,100 

If, for example, you want to see 11 elements in total (that is, ideally, 5 on the left, 5 spava, 1 current) and adapt for shifts (2 on the left, 1 current, 8 on the right - for page number 3), then the second option

 List<int> GeneratePages(int currentPage, int totalPages, int expectedpages) { var beforeCurrent = new Stack<int>(); var afterCurrent = new Queue<int>(); var expected = expectedpages - 1; var i = currentPage-1; var j = currentPage+1; while(expected > 0) { var local = expected; if (i > 0) { beforeCurrent.Push(i); i--; expected--; } if (j<=totalPages && expected > 0) { afterCurrent.Enqueue(j); j++; expected--; } if (local == expected) break; } var res = new List<int>(); while(beforeCurrent.Count>0) res.Add(beforeCurrent.Pop()); res.Add(currentPage); while(afterCurrent.Count>0) res.Add(afterCurrent.Dequeue()); return res; } 

Check

 Console.WriteLine( string.Join(",", GeneratePages(50, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(1, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(2, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(98, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(99, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(100, 100, 11))); Console.WriteLine( string.Join(",", GeneratePages(2, 5, 11))); 

Conclusion

 45,46,47,48,49,50,51,52,53,54,55 1,2,3,4,5,6,7,8,9,10,11 1,2,3,4,5,6,7,8,9,10,11 90,91,92,93,94,95,96,97,98,99,100 90,91,92,93,94,95,96,97,98,99,100 90,91,92,93,94,95,96,97,98,99,100 1,2,3,4,5 
  • Thank you for the answer, prompted some thoughts. In the end, the truth did according to Vlad's answer, it was all very beautiful there. - AK ♦
  • @AK but problems :) - tym32167

Made by answer @VladD:

 void Main() { var lastPage = 20; var currentPage = 3; var result = this.GetPaging(currentPage, lastPage); result.Dump(); } IEnumerable<int> GetPaging(int currentPage, int lastPage) { var maxBefore = 5; var maxAfter = 5; var first = currentPage - maxBefore; if(first < 1) first = 1; var last = currentPage + maxAfter; if(last > lastPage) last = lastPage; return Enumerable.Range(first, last - first); }