Есть у меня код, который выводит пагинацию на странице:
Это выводятся все элементы как есть - от первого до 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>
}
}
Проблемы начинаются, когда число страниц становится больше 10 (а частенько в пагинации и по триста страниц бывает) - они улетают за правую границу экрана.
Сижу думаю, какое условие нужно взять чтобы пагинация показывалась красиво.
Попробуем формализовать условие. Есть некоторая IEnumerable<int>
от 1 до Model.MaxPageCount и есть некоторое число PageNumber (текущий номер страницы) которое принадлежит этой последовательности.
Не уверен точно, но допустим мне надо получить не более пяти элементов ДО текущей страницы и не более пяти элементов ПОСЛЕ текущей страницы.
При этом я не знаю, как красиво обработать ситуацию, что если страниц ДО не хватает (допустим, мы смотрим страницу 3, тогда ДО будут страницы 1 и 2) то после наверное стоит взять чуть больше - не пять, а на на три больше. Но и не факт, что ПОСЛЕ хватит нужного числа страниц.
Вопрос скорее на красивый и простой алгоритм (как это принято делать в типичных пагинаторах?), возможно что конкретную формулу я и сам напишу. Если кто сталивался с подобной задачей и знает, как такое можно сделать - предложите вариант. Я смотрел разные варианты XPagedList на github, но какого-то удобного варианта не нашёл.
Что то типа такого?
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;
}
Проверка
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)));
Результаты
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
Если, например, хочется видеть в сумме 11 элементов (то есть в идеале 5 слева, 5 спава, 1 текущий) и адаптировать при сдвигах (2 слева, 1 текущий, 8 справа - для страницы номер 3), то ваот второй вариант
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;
}
Проверяем
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)));
Вывод
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
Сделано по ответу @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);
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Необходимо выводить время трековПолучается сделать, если например только mp3
Есть написанная мною программа на c# и в ней есть цикл whileНо когда я запускают программу с этим циклом, то нет того окна которое я сделал
Есть какие-либо способы создать PDF версии 14 через Microsoft Reporting Services? У меня получается только версия 1
Выдали тз, с самим тз проблем нетТолько Вот один момент , цитирую "надо прислать исходный код и запускаемый файл