Постраничный вывод информации в сообщение
Под постраничным выводом информации я подразумеваю сообщений с inline кнопками вперед и назад, при нажатие на эти кнопки изменяются данные сообщения.

Создадим перечисление
[InlineCommand]
public enum CustomTHeaderTwo
{
[Description("Пример 1")]
ExampleOne = 600,
[Description("Пример 2")]
ExampleTwo,
[Description("Пример 3")]
ExampleThree,
[Description("Пример страниц")]
CustomPageHeader,
[Description("Пример страниц2")]
CustomPageHeader2,
}
Подготовим 2 тестовых списка с текстом сообщений:
//Тестовые данные 1
static List<string> pageData = new List<string>()
{
"Данные страница 1",
"Данные страница 2",
"Данные страница 3",
"Данные страница 4",
"Данные страница 5"
};
//Тестовые данные 2
static List<string> pageDataTwo = new List<string>()
{
"TestДанные страница 1",
"TestДанные страница 2",
"TestДанные страница 3",
"TestДанные страница 4",
"TestДанные страница 5"
};
Для генерации постраничного меню используется следующий методы:
/// <summary>
/// Генерирует меню для постраничного вывода
/// </summary>
/// <param name="currentPage">Текущая страница</param>
/// <param name="pageCount">Всего страниц</param>
/// <param name="nextPageMarker">Маркер nextpage</param>
/// <param name="previousPageMarker">Маркер prevpage</param>
/// <param name="currentPageMarker">Маркер currentPage</param>
/// <param name="addMenu">Дополнительное меню с которым требуется объединить данные</param>
/// <returns>Постраничное inline menu</returns>
public static InlineKeyboardMarkup GetPageMenu(
int currentPage,
int pageCount,
InlineKeyboardMarkup addMenu,
Enum enumToInt,
string nextPageMarker = "➡️",
string previousPageMarker = "⬅️",
string currentPageMarker = "")
/// <summary>
/// Генерирует меню для постраничного вывода
/// </summary>
/// <param name="currentPage">Текущая страница</param>
/// <param name="pageCount">Всего страниц</param>
/// <param name="nextPageMarker">Маркер nextpage</param>
/// <param name="previousPageMarker">Маркер prevpage</param>
/// <param name="button">Кнопка обработчик в центре</param>
/// <param name="addMenu">Дополнительное меню с которым требуется объединить данные</param>
/// <returns>Постраничное inline menu</returns>
public static InlineKeyboardMarkup GetPageMenu(
int currentPage,
int pageCount,
InlineKeyboardMarkup addMenu,
Enum enumToInt,
string nextPageMarker = "➡️",
string previousPageMarker = "⬅️",
IInlineContent button = null)
/// <summary>
/// Генерирует меню для постраничного вывода
/// </summary>
/// <param name="currentPage">Текущая страница</param>
/// <param name="pageCount">Всего страниц</param>
/// <param name="nextPageMarker">Маркер nextpage</param>
/// <param name="previousPageMarker">Маркер prevpage</param>
/// <param name="currentPageMarker">Маркер currentPage</param>
/// <returns>Постраничное inline menu</returns>
public static InlineKeyboardMarkup GetPageMenu(
Enum enumToInt,
int currentPage,
int pageCount,
string nextPageMarker = "➡️",
string previousPageMarker = "⬅️",
string currentPageMarker = "")
/// <summary>
/// Генерирует меню для постраничного вывода
/// </summary>
/// <param name="currentPage">Текущая страница</param>
/// <param name="pageCount">Всего страниц</param>
/// <param name="nextPageMarker">Маркер nextpage</param>
/// <param name="enumToInt">Заголовок команды</param>
/// <param name="previousPageMarker">Маркер prevpage</param>
/// <param name="button">Кнопка обработчик в центре</param>
/// <returns>Постраничное inline menu</returns>
public static InlineKeyboardMarkup GetPageMenu(
int currentPage,
int pageCount,
Enum enumToInt,
string nextPageMarker = "➡️",
string previousPageMarker = "⬅️",
IInlineContent button = null)
/// <summary>
/// Генерирует меню для постраничного вывода
/// </summary>
/// <param name="currentPage">Текущая страница</param>
/// <param name="pageCount">Всего страниц</param>
/// <param name="nextPageMarker">Маркер nextpage</param>
/// <param name="enumToInt">Заголовок команды</param>
/// <param name="previousPageMarker">Маркер prevpage</param>
/// <param name="customButtons">Кнопки обработчики</param>
/// <returns>Постраничное inline menu</returns>
public static InlineKeyboardMarkup GetPageMenu(
int currentPage,
int pageCount,
Enum enumToInt,
List<IInlineContent> customButtons,
string nextPageMarker = "➡️",
string previousPageMarker = "⬅️")
Данный метод генерировать меню с кнопка вперед и назад, так и с дополнительной кнопкой обработки по центру. Допустим мы с помощью этого может добавлять/удалять объект из избранного.
Пример: Данный метод будет генерировать меню с кнопка вперед и назад, так и с дополнительной кнопкой обработки по центру. Допустим мы с помощью этого может добавлять/удалять объект из избранного.
Для постраничного вывода информации используется метод расширения GetPaged:
/// <summary>
/// Вывод данных постранично
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query">Коллекция данных</param>
/// <param name="page">Страница</param>
/// <param name="pageSize">Размер страницы</param>
/// <returns>Страница данных с доп информацией</returns>
public static async Task<PagedResult<T>> GetPaged<T>(this IList<T> query,
int page, int pageSize) where T : class
{
var result = new PagedResult<T>();
result.CurrentPage = page;
result.PageSize = pageSize;
result.RowCount = query.Count();
/// <summary>
/// Помогает разбить данные постранично.
/// </summary>
public static class PageExtension
{
#region Методы
/// <summary>
/// Вывод данных постранично.
/// </summary>
/// <typeparam name="T">Тип.</typeparam>
/// <param name="query">Коллекция данных.</param>
/// <param name="page">Страница.</param>
/// <param name="pageSize">Размер страницы.</param>
/// <returns>Страница данных с доп информацией.</returns>
public static async Task<PagedResult<T>> GetPaged<T>(this IEnumerable<T> query, int page, int pageSize)
where T : class
{
var result = new PagedResult<T>();
result.CurrentPage = page;
result.PageSize = pageSize;
result.RowCount = query.Count();
var pageCount = (double)result.RowCount / pageSize;
result.PageCount = (int)Math.Ceiling(pageCount);
var skip = (page - 1) * pageSize;
result.Results = query.Skip(skip).Take(pageSize).ToList();
return result;
}
#endregion
}
За его основу была взята эта статья по работе постраничным выводом из Entity framework
Ниже представлен полный пример.
public class ExamplePage
{
//Тестовые данные 1
static List<string> pageData = new List<string>()
{
"Данные страница 1",
"Данные страница 2",
"Данные страница 3",
"Данные страница 4",
"Данные страница 5"
};
//Тестовые данные 2
static List<string> pageDataTwo = new List<string>()
{
"TestДанные страница 1",
"TestДанные страница 2",
"TestДанные страница 3",
"TestДанные страница 4",
"TestДанные страница 5"
};
/// <summary>
/// Напишите в чате "pages"
/// </summary>
[ReplyMenuHandler("pages")]
public static async Task ExamplePages(ITelegramBotClient botClient, Update update)
{
//Беру текст для первого сообщения
string msg = pageData[0];
//Получаю контент с 1 страницы с размером страницы 1
var data = await pageData.GetPaged<string>(1, 1);
//Генерирую меню постраничного вывода с заголовком
var generateMenu = MenuGenerator.GetPageMenu(data.CurrentPage, data.PageCount, CustomTHeaderTwo.CustomPageHeader);
var option = new OptionMessage();
option.MenuInlineKeyboardMarkup = generateMenu;
var message = await Helpers.Message.Send(botClient, update, msg, option);
}
/// <summary>
/// Напишите в чате "pagestwo"
/// </summary>
[ReplyMenuHandler("pagestwo")]
public static async Task ExamplePagesTwo(ITelegramBotClient botClient, Update update)
{
//Беру текст для первого сообщения
string msg = pageDataTwo[0];
//Получаю контент с 1 страницы с размером страницы 1
var data = await pageDataTwo.GetPaged<string>(1, 1);
//Генерирую меню постраничного вывода с заголовком
var generateMenu = MenuGenerator.GetPageMenu(data.CurrentPage, data.PageCount, CustomTHeaderTwo.CustomPageHeader2);
var option = new OptionMessage();
option.MenuInlineKeyboardMarkup = generateMenu;
var message = await Helpers.Message.Send(botClient, update, msg, option);
}
/// <summary>
/// callback обработка постраничного вывода
/// Обрабатывает одну точку входа
/// </summary>
[InlineCallbackHandler<PRTelegramBotCommand>(PRTelegramBotCommand.NextPage, PRTelegramBotCommand.PreviousPage, PRTelegramBotCommand.CurrentPage)]
public static async Task InlinenPage(ITelegramBotClient botClient, Update update)
{
try
{
//Попытка преобразовать callback данные к требуемому типу
if (update.CallbackQuery?.Data != null)
{
var command = InlineCallback<PageTCommand>.GetCommandByCallbackOrNull(update.CallbackQuery.Data);
if (command != null)
{
//Получаю заголовок из данных
CustomTHeaderTwo header = (CustomTHeaderTwo)command.Data.Header;
//обрабатываю данные по заголовку
if(header == CustomTHeaderTwo.CustomPageHeader)
{
//Получаю номер страницы и указываю размер страницы
var data = await pageData.GetPaged<string>(command.Data.Page, 1);
//Генерирую постраничное меню
var button = new InlineCallback("⭐", CustomTHeader.CustomButton);
var generateMenu = MenuGenerator.GetPageMenu(data.CurrentPage, data.PageCount, CustomTHeaderTwo.CustomPageHeader,button: button);
//Получаю результат из постраничного вывода
var pageResult = data.Results;
var option = new OptionMessage();
option.MenuInlineKeyboardMarkup = generateMenu;
string msg = "";
if (pageResult.Count > 0)
{
msg = pageResult.FirstOrDefault();
}
else
{
msg = "Нечего не найдено";
}
//Редактирую текущую страницу
await Helpers.Message.Edit(botClient, update, msg, option);
}
//обрабатываю данные по заголовку
else if (header == CustomTHeaderTwo.CustomPageHeader2)
{
//Получаю номер страницы и указываю размер страницы
var data = await pageDataTwo.GetPaged<string>(command.Data.Page, 1);
//Генерирую постраничное меню
var generateMenu = MenuGenerator.GetPageMenu(data.CurrentPage, data.PageCount, CustomTHeaderTwo.CustomPageHeader2);
//Получаю результат из постраничного вывода
var pageResult = data.Results;
var option = new OptionMessage();
option.MenuInlineKeyboardMarkup = generateMenu;
string msg = "";
if (pageResult.Count > 0)
{
msg = pageResult.FirstOrDefault();
}
else
{
msg = "Нечего не найдено";
}
//Редактирую текущую страницу
await Helpers.Message.Edit(botClient, update, msg, option);
}
}
}
}
catch (Exception ex)
{
//Обработка исключения
}
}
[InlineCallbackHandler<CustomTHeader>(CustomTHeader.CustomButton)]
public static async Task FavoriteMessage(ITelegramBotClient botClient, Update update)
{
string msg = "Меню";
//Создаем настройки сообщения
var option = new OptionMessage();
//Создаем список для меню
var menuList = new List<KeyboardButton>();
//Добавляем кнопку с текстом
menuList.Add(new KeyboardButton("Кнопка 1"));
//Добавляем кнопку с запросом на контакт пользователя
menuList.Add(KeyboardButton.WithRequestContact("Отправить свой контакт"));
//Добавляем кнопку с запросом на локацию пользователя
menuList.Add(KeyboardButton.WithRequestLocation("Отправить свою локацию"));
//Добавляем кнопку с запросом отправки чата боту
menuList.Add(KeyboardButton.WithRequestChat("Отправить группу боту", new KeyboardButtonRequestChat(2, true) ));
//Добавляем кнопку с запросом отправки пользователя боту
menuList.Add(KeyboardButton.WithRequestUsers("Отправить пользователя боту", new KeyboardButtonRequestUsers() { RequestId = 1 }));
//Добавляем кнопку с отправкой опроса
menuList.Add(KeyboardButton.WithRequestPoll("Отправить свою голосование"));
//Добавляем кнопку с запросом работы с WebApp
menuList.Add(KeyboardButton.WithWebApp("WebApp", new WebAppInfo() { Url = "https://prethink.github.io/telegram/webapp.html" }));
//Генерируем reply меню
//1 столбец, коллекция пунктов меню, вертикальное растягивание меню, пункт в самом низу по умолчанию
var menu = MenuGenerator.ReplyKeyboard(1, menuList, true, "Главное меню");
//Добавляем в настройки меню
option.MenuReplyKeyboardMarkup = menu;
await Helpers.Message.Send(botClient, update, msg, option);
}
}
Результаты работы:



Last updated