MAJOR CHANGE for ButtonGrids, Dynamic data sources, etc

- introducing a dynamic data source class (IDataSource)
- introducing a ButtonRow class for better managability
- replacing that List<ButtonBase> with ButtonRow object
- introducing ButtonFormDataSource with special methods for ButtonGrid controls
- updating ButtonGrid and refactoring of the Load/Action methods
- updating CheckButtonList and refactoring of the Load/Action methods
- updating TaggedButtonGrid and refactoring of the Load/Action methods
- adding example to the Test project
This commit is contained in:
FlorianDahn 2021-07-26 15:10:10 +02:00
parent 894d0799c8
commit 71433c0e4e
14 changed files with 1225 additions and 266 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form; using TelegramBotBase.Form;
namespace TelegramBotBase.Args namespace TelegramBotBase.Args
@ -18,6 +19,8 @@ namespace TelegramBotBase.Args
public object Tag { get; set; } public object Tag { get; set; }
public ButtonRow Row { get; set; }
public ButtonClickedEventArgs() public ButtonClickedEventArgs()
{ {
@ -36,5 +39,11 @@ namespace TelegramBotBase.Args
this.Index = Index; this.Index = Index;
} }
public ButtonClickedEventArgs(ButtonBase button, int Index, ButtonRow row)
{
this.Button = button;
this.Index = Index;
this.Row = row;
}
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form; using TelegramBotBase.Form;
namespace TelegramBotBase.Args namespace TelegramBotBase.Args
@ -17,7 +18,7 @@ namespace TelegramBotBase.Args
/// <summary> /// <summary>
/// Contains all buttons within this row, excluding the checkbox. /// Contains all buttons within this row, excluding the checkbox.
/// </summary> /// </summary>
public List<ButtonBase> Row { get; set; } public ButtonRow Row { get; set; }
/// <summary> /// <summary>
@ -31,7 +32,7 @@ namespace TelegramBotBase.Args
} }
public CheckedChangedEventArgs(List<ButtonBase> row, int Index, bool Checked) public CheckedChangedEventArgs(ButtonRow row, int Index, bool Checked)
{ {
this.Row = row; this.Row = row;
this.Index = Index; this.Index = Index;

View File

@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args; using TelegramBotBase.Args;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Datasources;
using TelegramBotBase.Enums; using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions; using TelegramBotBase.Exceptions;
using TelegramBotBase.Form; using TelegramBotBase.Form;
@ -30,7 +31,26 @@ namespace TelegramBotBase.Controls.Hybrid
private readonly EventHandlerList Events = new EventHandlerList(); private readonly EventHandlerList Events = new EventHandlerList();
public ButtonForm ButtonsForm { get; set; } /// <summary>
///
/// </summary>
[Obsolete("This property is obsolete. Please use the DataSource property instead.")]
public ButtonForm ButtonsForm
{
get
{
return DataSource.ButtonForm;
}
set
{
DataSource = new ButtonFormDataSource(value);
}
}
/// <summary>
/// Data source of the items.
/// </summary>
public ButtonFormDataSource DataSource { get; set; }
public int? MessageId { get; set; } public int? MessageId { get; set; }
@ -89,12 +109,12 @@ namespace TelegramBotBase.Controls.Hybrid
/// <summary> /// <summary>
/// Layout of the buttons which should be displayed always on top. /// Layout of the buttons which should be displayed always on top.
/// </summary> /// </summary>
public List<ButtonBase> HeadLayoutButtonRow { get; set; } public ButtonRow HeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// Layout of columns which should be displayed below the header /// Layout of columns which should be displayed below the header
/// </summary> /// </summary>
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; } public ButtonRow SubHeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// Defines which type of Button Keyboard should be rendered. /// Defines which type of Button Keyboard should be rendered.
@ -123,8 +143,7 @@ namespace TelegramBotBase.Controls.Hybrid
public ButtonGrid() public ButtonGrid()
{ {
this.ButtonsForm = new ButtonForm(); this.DataSource = new ButtonFormDataSource();
} }
@ -136,7 +155,7 @@ namespace TelegramBotBase.Controls.Hybrid
public ButtonGrid(ButtonForm form) public ButtonGrid(ButtonForm form)
{ {
this.ButtonsForm = form; this.DataSource = new ButtonFormDataSource(form);
} }
@ -188,22 +207,49 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler) if (!result.IsFirstHandler)
return; return;
if (result.MessageText == null) if (result.MessageText == null || result.MessageText == "")
return; return;
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) var matches = new List<ButtonRow>();
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) ButtonRow match = null;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText); int index = -1;
var index = ButtonsForm.FindRowByButton(button); if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
if (button != null)
{ {
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); match = HeadLayoutButtonRow;
goto check;
}
//Remove button click message if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
if (this.DeleteReplyMessage) {
await Device.DeleteMessage(result.MessageId); match = SubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.MessageText);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
//var index = bf.FindRowByButton(button);
check:
//Remove button click message
if (this.DeleteReplyMessage)
await Device.DeleteMessage(result.MessageId);
if (match != null)
{
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
result.Handled = true; result.Handled = true;
return; return;
@ -261,22 +307,48 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler) if (!result.IsFirstHandler)
return; return;
await result.ConfirmAction(this.ConfirmationText ?? "");
//Find clicked button depending on Text or Value (depending on markup type) //Find clicked button depending on Text or Value (depending on markup type)
if (this.KeyboardType != eKeyboardType.InlineKeyBoard) if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
return; return;
await result.ConfirmAction(this.ConfirmationText ?? "");
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) ButtonRow match = null;
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) int index = -1;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
var index = ButtonsForm.FindRowByButton(button); if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
if (button != null)
{ {
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); match = HeadLayoutButtonRow;
goto check;
}
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
match = SubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.RawData, false);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var bf = DataSource.ButtonForm;
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
//var index = bf.FindRowByButton(button);
check:
if (match != null)
{
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
result.Handled = true; result.Handled = true;
return; return;
@ -313,28 +385,28 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
case eKeyboardType.InlineKeyBoard: case eKeyboardType.InlineKeyBoard:
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
} }
break; break;
case eKeyboardType.ReplyKeyboard: case eKeyboardType.ReplyKeyboard:
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
} }
break; break;
@ -351,22 +423,21 @@ namespace TelegramBotBase.Controls.Hybrid
this.RenderNecessary = false; this.RenderNecessary = false;
Message m = null; ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, (this.EnableSearch ? this.SearchQuery : null));
ButtonForm form = this.ButtonsForm;
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
{ //{
form = form.FilterDuplicate(this.SearchQuery, true); // form = form.FilterDuplicate(this.SearchQuery, true);
} //}
else //else
{ //{
form = form.Duplicate(); // form = form.Duplicate();
} //}
if (this.EnablePaging) if (this.EnablePaging)
{ {
form = GeneratePagingView(form); IntegratePagingView(form);
} }
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0) if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
@ -386,26 +457,37 @@ namespace TelegramBotBase.Controls.Hybrid
} }
} }
Message m = null;
switch (this.KeyboardType) switch (this.KeyboardType)
{ {
//Reply Keyboard could only be updated with a new keyboard. //Reply Keyboard could only be updated with a new keyboard.
case eKeyboardType.ReplyKeyboard: case eKeyboardType.ReplyKeyboard:
if (this.MessageId != null)
if (form.Count == 0)
{ {
if (form.Count == 0) if (this.MessageId != null)
{ {
await this.Device.HideReplyKeyboard(); await this.Device.HideReplyKeyboard();
this.MessageId = null; this.MessageId = null;
return;
} }
if (this.DeletePreviousMessage) return;
await this.Device.DeleteMessage(this.MessageId.Value);
} }
if (form.Count == 0) //if (this.MessageId != null)
return; //{
// if (form.Count == 0)
// {
// await this.Device.HideReplyKeyboard();
// this.MessageId = null;
// return;
// }
//}
//if (form.Count == 0)
// return;
var rkm = (ReplyKeyboardMarkup)form; var rkm = (ReplyKeyboardMarkup)form;
@ -413,6 +495,10 @@ namespace TelegramBotBase.Controls.Hybrid
rkm.OneTimeKeyboard = this.OneTimeKeyboard; rkm.OneTimeKeyboard = this.OneTimeKeyboard;
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false); m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
//Prevent flicker of keyboard
if (this.DeletePreviousMessage && this.MessageId != null)
await this.Device.DeleteMessage(this.MessageId.Value);
break; break;
case eKeyboardType.InlineKeyBoard: case eKeyboardType.InlineKeyBoard:
@ -443,47 +529,31 @@ namespace TelegramBotBase.Controls.Hybrid
} }
private ButtonForm GeneratePagingView(ButtonForm dataForm) private void IntegratePagingView(ButtonForm dataForm)
{ {
ButtonForm bf = new ButtonForm();
for (int i = 0; i < this.MaximumRow - LayoutRows; i++)
{
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
if (it > dataForm.Rows - 1)
break;
bf.AddButtonRow(dataForm[it]);
}
//No Items //No Items
if (this.ButtonsForm.Count == 0) if (dataForm.Rows == 0)
{ {
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$")); dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
} }
if (this.IsNavigationBarVisible) if (this.IsNavigationBarVisible)
{ {
//🔍 //🔍
List<ButtonBase> lst = new List<ButtonBase>(); ButtonRow row = new ButtonRow();
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$")); row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$")); row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
lst.Add(new ButtonBase(NextPageLabel, "$next$")); row.Add(new ButtonBase(NextPageLabel, "$next$"));
if (this.EnableSearch) if (this.EnableSearch)
{ {
lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$")); row.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
} }
bf.InsertButtonRow(0, lst); dataForm.InsertButtonRow(0, row);
bf.AddButtonRow(lst); dataForm.AddButtonRow(row);
} }
return bf;
} }
public bool PagingNecessary public bool PagingNecessary
@ -545,7 +615,7 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
get get
{ {
return this.LayoutRows + ButtonsForm.Rows; return this.LayoutRows + DataSource.RowCount;
} }
} }
@ -572,24 +642,40 @@ namespace TelegramBotBase.Controls.Hybrid
} }
} }
/// <summary>
/// Returns the number of item rows per page.
/// </summary>
public int ItemRowsPerPage
{
get
{
return this.MaximumRow - this.LayoutRows;
}
}
/// <summary>
/// Return the number of pages.
/// </summary>
public int PageCount public int PageCount
{ {
get get
{ {
if (this.ButtonsForm.Count == 0) if (DataSource.RowCount == 0)
return 1; return 1;
var bf = this.ButtonsForm; //var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
{
bf = bf.FilterDuplicate(this.SearchQuery);
}
if (bf.Rows == 0) //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
//{
// bf = bf.FilterDuplicate(this.SearchQuery);
//}
if (max == 0)
return 1; return 1;
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows))); return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
} }
} }

View File

@ -0,0 +1,112 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using TelegramBotBase.Form;
namespace TelegramBotBase.Controls.Hybrid
{
[DebuggerDisplay("{Count} columns")]
public class ButtonRow
{
List<ButtonBase> __buttons = new List<ButtonBase>();
public ButtonRow()
{
}
public ButtonRow(params ButtonBase[] buttons)
{
__buttons = buttons.ToList();
}
public ButtonBase this[int index]
{
get
{
return __buttons[index];
}
}
public int Count
{
get
{
return __buttons.Count;
}
}
public void Add(ButtonBase button)
{
__buttons.Add(button);
}
public void AddRange(ButtonBase button)
{
__buttons.Add(button);
}
public void Insert(int index, ButtonBase button)
{
__buttons.Insert(index, button);
}
public IEnumerator<ButtonBase> GetEnumerator()
{
return __buttons.GetEnumerator();
}
public ButtonBase[] ToArray()
{
return __buttons.ToArray();
}
public List<ButtonBase> ToList()
{
return __buttons.ToList();
}
public bool Matches(String text, bool useText = true)
{
foreach (var b in __buttons)
{
if (useText && b.Text.Trim().Equals(text, StringComparison.InvariantCultureIgnoreCase))
return true;
if (!useText && b.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase))
return true;
}
return false;
}
/// <summary>
/// Returns the button inside of the row which matches.
/// </summary>
/// <param name="text"></param>
/// <param name="useText"></param>
/// <returns></returns>
public ButtonBase GetButtonMatch(String text, bool useText = true)
{
foreach (var b in __buttons)
{
if (useText && b.Text.Trim().Equals(text, StringComparison.InvariantCultureIgnoreCase))
return b;
if (!useText && b.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase))
return b;
}
return null;
}
public static implicit operator ButtonRow(List<ButtonBase> list)
{
return new ButtonRow() { __buttons = list };
}
}
}

View File

@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args; using TelegramBotBase.Args;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Datasources;
using TelegramBotBase.Enums; using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions; using TelegramBotBase.Exceptions;
using TelegramBotBase.Form; using TelegramBotBase.Form;
@ -32,7 +33,23 @@ namespace TelegramBotBase.Controls.Hybrid
private readonly EventHandlerList Events = new EventHandlerList(); private readonly EventHandlerList Events = new EventHandlerList();
public ButtonForm ButtonsForm { get; set; } [Obsolete("This property is obsolete. Please use the DataSource property instead.")]
public ButtonForm ButtonsForm
{
get
{
return DataSource.ButtonForm;
}
set
{
DataSource = new ButtonFormDataSource(value);
}
}
/// <summary>
/// Data source of the items.
/// </summary>
public ButtonFormDataSource DataSource { get; set; }
List<int> CheckedRows { get; set; } = new List<int>(); List<int> CheckedRows { get; set; } = new List<int>();
@ -51,6 +68,11 @@ namespace TelegramBotBase.Controls.Hybrid
public bool DeletePreviousMessage { get; set; } = true; public bool DeletePreviousMessage { get; set; } = true;
/// <summary>
/// Removes the reply message from a user.
/// </summary>
public bool DeleteReplyMessage { get; set; } = true;
/// <summary> /// <summary>
/// Parsemode of the message. /// Parsemode of the message.
/// </summary> /// </summary>
@ -92,12 +114,12 @@ namespace TelegramBotBase.Controls.Hybrid
/// <summary> /// <summary>
/// Layout of the buttons which should be displayed always on top. /// Layout of the buttons which should be displayed always on top.
/// </summary> /// </summary>
public List<ButtonBase> HeadLayoutButtonRow { get; set; } public ButtonRow HeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// Layout of columns which should be displayed below the header /// Layout of columns which should be displayed below the header
/// </summary> /// </summary>
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; } public ButtonRow SubHeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// Defines which type of Button Keyboard should be rendered. /// Defines which type of Button Keyboard should be rendered.
@ -126,7 +148,7 @@ namespace TelegramBotBase.Controls.Hybrid
public CheckedButtonList() public CheckedButtonList()
{ {
this.ButtonsForm = new ButtonForm(); this.DataSource = new ButtonFormDataSource();
} }
@ -139,7 +161,7 @@ namespace TelegramBotBase.Controls.Hybrid
public CheckedButtonList(ButtonForm form) public CheckedButtonList(ButtonForm form)
{ {
this.ButtonsForm = form; this.DataSource = new ButtonFormDataSource(form);
} }
public event AsyncEventHandler<ButtonClickedEventArgs> ButtonClicked public event AsyncEventHandler<ButtonClickedEventArgs> ButtonClicked
@ -198,16 +220,50 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler) if (!result.IsFirstHandler)
return; return;
if (result.MessageText == null) if (result.MessageText == null || result.MessageText == "")
return; return;
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) var matches = new List<ButtonRow>();
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) ButtonRow match = null;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText); int index = -1;
var index = ButtonsForm.FindRowByButton(button); if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
match = HeadLayoutButtonRow;
goto check;
}
if (button == null) if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
match = SubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.MessageText);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
//var index = bf.FindRowByButton(button);
check:
//Remove button click message
if (this.DeleteReplyMessage)
await Device.DeleteMessage(result.MessageId);
if (match == null)
{ {
if (result.MessageText == PreviousPageLabel) if (result.MessageText == PreviousPageLabel)
{ {
@ -226,7 +282,7 @@ namespace TelegramBotBase.Controls.Hybrid
else if (result.MessageText.EndsWith(CheckedIconLabel)) else if (result.MessageText.EndsWith(CheckedIconLabel))
{ {
var s = result.MessageText.Split(' ', '.'); var s = result.MessageText.Split(' ', '.');
index = int.Parse(s[0]); index = int.Parse(s[0]) - 1;
if (!this.CheckedRows.Contains(index)) if (!this.CheckedRows.Contains(index))
return; return;
@ -241,7 +297,7 @@ namespace TelegramBotBase.Controls.Hybrid
else if (result.MessageText.EndsWith(UncheckedIconLabel)) else if (result.MessageText.EndsWith(UncheckedIconLabel))
{ {
var s = result.MessageText.Split(' ', '.'); var s = result.MessageText.Split(' ', '.');
index = int.Parse(s[0]); index = int.Parse(s[0]) - 1;
if (this.CheckedRows.Contains(index)) if (this.CheckedRows.Contains(index))
return; return;
@ -285,14 +341,18 @@ namespace TelegramBotBase.Controls.Hybrid
} }
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
//Remove button click message
if (this.DeletePreviousMessage)
await Device.DeleteMessage(result.MessageId);
result.Handled = true; result.Handled = true;
//await OnButtonClicked(new ButtonClickedEventArgs(button, index));
////Remove button click message
//if (this.DeletePreviousMessage)
// await Device.DeleteMessage(result.MessageId);
//result.Handled = true;
} }
public async override Task Action(MessageResult result, string value = null) public async override Task Action(MessageResult result, string value = null)
@ -309,20 +369,55 @@ namespace TelegramBotBase.Controls.Hybrid
await result.ConfirmAction(this.ConfirmationText ?? ""); await result.ConfirmAction(this.ConfirmationText ?? "");
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) ButtonRow match = null;
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) int index = -1;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
var index = ButtonsForm.FindRowByButton(button); if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
if (button != null)
{ {
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); match = HeadLayoutButtonRow;
goto check;
}
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
match = SubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.RawData, false);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var bf = DataSource.ButtonForm;
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
//var index = bf.FindRowByButton(button);
check:
if (match != null)
{
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
result.Handled = true; result.Handled = true;
return; return;
} }
//if (button != null)
//{
// await OnButtonClicked(new ButtonClickedEventArgs(button, index));
// result.Handled = true;
// return;
//}
switch (result.RawData) switch (result.RawData)
{ {
case "$previous$": case "$previous$":
@ -396,28 +491,28 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
case eKeyboardType.InlineKeyBoard: case eKeyboardType.InlineKeyBoard:
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
} }
break; break;
case eKeyboardType.ReplyKeyboard: case eKeyboardType.ReplyKeyboard:
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
} }
break; break;
@ -436,7 +531,7 @@ namespace TelegramBotBase.Controls.Hybrid
Message m = null; Message m = null;
ButtonForm form = this.ButtonsForm; ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, null);
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
//{ //{
@ -444,12 +539,12 @@ namespace TelegramBotBase.Controls.Hybrid
//} //}
//else //else
//{ //{
form = form.Duplicate(); //form = form.Duplicate();
//} //}
if (this.EnablePaging) if (this.EnablePaging)
{ {
form = GeneratePagingView(form); IntegratePagingView(form);
} }
else else
{ {
@ -458,18 +553,18 @@ namespace TelegramBotBase.Controls.Hybrid
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0) if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
{ {
form.InsertButtonRow(0, this.HeadLayoutButtonRow); form.InsertButtonRow(0, this.HeadLayoutButtonRow.ToArray());
} }
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0) if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
{ {
if (this.IsNavigationBarVisible) if (this.IsNavigationBarVisible)
{ {
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow); form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
} }
else else
{ {
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow); form.InsertButtonRow(1, this.SubHeadLayoutButtonRow.ToArray());
} }
} }
@ -478,21 +573,19 @@ namespace TelegramBotBase.Controls.Hybrid
//Reply Keyboard could only be updated with a new keyboard. //Reply Keyboard could only be updated with a new keyboard.
case eKeyboardType.ReplyKeyboard: case eKeyboardType.ReplyKeyboard:
if (this.MessageId != null) if (form.Count == 0)
{ {
if (form.Count == 0) if (this.MessageId != null)
{ {
await this.Device.HideReplyKeyboard(); await this.Device.HideReplyKeyboard();
this.MessageId = null; this.MessageId = null;
return;
} }
if (this.DeletePreviousMessage) return;
await this.Device.DeleteMessage(this.MessageId.Value);
} }
if (form.Count == 0) //if (form.Count == 0)
return; // return;
var rkm = (ReplyKeyboardMarkup)form; var rkm = (ReplyKeyboardMarkup)form;
@ -500,6 +593,10 @@ namespace TelegramBotBase.Controls.Hybrid
rkm.OneTimeKeyboard = this.OneTimeKeyboard; rkm.OneTimeKeyboard = this.OneTimeKeyboard;
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false); m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
//Prevent flicker of keyboard
if (this.DeletePreviousMessage && this.MessageId != null)
await this.Device.DeleteMessage(this.MessageId.Value);
break; break;
case eKeyboardType.InlineKeyBoard: case eKeyboardType.InlineKeyBoard:
@ -524,58 +621,52 @@ namespace TelegramBotBase.Controls.Hybrid
} }
private ButtonForm GeneratePagingView(ButtonForm dataForm) private void IntegratePagingView(ButtonForm dataForm)
{ {
//No Items
if (dataForm.Rows == 0)
{
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
}
ButtonForm bf = new ButtonForm(); ButtonForm bf = new ButtonForm();
bf = PrepareCheckableLayout(dataForm); bf = PrepareCheckableLayout(dataForm);
//No Items
if (this.ButtonsForm.Count == 0)
{
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
}
if (this.IsNavigationBarVisible) if (this.IsNavigationBarVisible)
{ {
//🔍 //🔍
List<ButtonBase> lst = new List<ButtonBase>(); ButtonRow row = new ButtonRow();
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$")); row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$")); row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
lst.Add(new ButtonBase(NextPageLabel, "$next$")); row.Add(new ButtonBase(NextPageLabel, "$next$"));
//if (this.EnableSearch)
//{
// lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
//}
bf.InsertButtonRow(0, lst); dataForm.InsertButtonRow(0, row);
bf.AddButtonRow(lst); dataForm.AddButtonRow(row);
} }
return bf;
} }
private ButtonForm PrepareCheckableLayout(ButtonForm dataForm) private ButtonForm PrepareCheckableLayout(ButtonForm dataForm)
{ {
var bf = new ButtonForm(); var bf = new ButtonForm();
for (int i = 0; i < this.MaximumRow - LayoutRows; i++) for (int i = 0; i < dataForm.Rows; i++)
{ {
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i; int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
if (it > dataForm.Rows - 1) //if (it > dataForm.Rows - 1)
break; // break;
var r = dataForm[it]; var r = dataForm[i];
String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel; String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel;
//On reply keyboards we need a unique text. //On reply keyboards we need a unique text.
if (this.KeyboardType == eKeyboardType.ReplyKeyboard) if (this.KeyboardType == eKeyboardType.ReplyKeyboard)
{ {
s = $"{it}. " + s; s = $"{it + 1}. " + s;
} }
if (CheckedRows.Contains(it)) if (CheckedRows.Contains(it))
@ -652,7 +743,7 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
get get
{ {
return this.LayoutRows + ButtonsForm.Rows; return this.LayoutRows + DataSource.RowCount;
} }
} }
@ -679,24 +770,37 @@ namespace TelegramBotBase.Controls.Hybrid
} }
} }
/// <summary>
/// Returns the number of item rows per page.
/// </summary>
public int ItemRowsPerPage
{
get
{
return this.MaximumRow - this.LayoutRows;
}
}
public int PageCount public int PageCount
{ {
get get
{ {
if (this.ButtonsForm.Count == 0) if (DataSource.RowCount == 0)
return 1; return 1;
var bf = this.ButtonsForm; //var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
var max = this.DataSource.RowCount;
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
//{ //{
// bf = bf.FilterDuplicate(this.SearchQuery); // bf = bf.FilterDuplicate(this.SearchQuery);
//} //}
if (bf.Rows == 0) if (max == 0)
return 1; return 1;
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows))); return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
} }
} }

View File

@ -7,9 +7,11 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.InlineQueryResults;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args; using TelegramBotBase.Args;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Datasources;
using TelegramBotBase.Enums; using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions; using TelegramBotBase.Exceptions;
using TelegramBotBase.Form; using TelegramBotBase.Form;
@ -30,7 +32,23 @@ namespace TelegramBotBase.Controls.Hybrid
private readonly EventHandlerList Events = new EventHandlerList(); private readonly EventHandlerList Events = new EventHandlerList();
public ButtonForm ButtonsForm { get; set; } [Obsolete("This property is obsolete. Please use the DataSource property instead.")]
public ButtonForm ButtonsForm
{
get
{
return DataSource.ButtonForm;
}
set
{
DataSource = new ButtonFormDataSource(value);
}
}
/// <summary>
/// Data source of the items.
/// </summary>
public ButtonFormDataSource DataSource { get; set; }
public int? MessageId { get; set; } public int? MessageId { get; set; }
@ -62,6 +80,11 @@ namespace TelegramBotBase.Controls.Hybrid
/// </summary> /// </summary>
public bool EnablePaging { get; set; } = false; public bool EnablePaging { get; set; } = false;
/// <summary>
/// Shows un-/check all tags options
/// </summary>
public bool EnableCheckAllTools { get; set; } = false;
/// <summary> /// <summary>
/// Enabled a search function. /// Enabled a search function.
/// </summary> /// </summary>
@ -87,15 +110,24 @@ namespace TelegramBotBase.Controls.Hybrid
public String BackLabel = Localizations.Default.Language["ButtonGrid_Back"]; public String BackLabel = Localizations.Default.Language["ButtonGrid_Back"];
public String CheckAllLabel = Localizations.Default.Language["ButtonGrid_CheckAll"];
public String UncheckAllLabel = Localizations.Default.Language["ButtonGrid_UncheckAll"];
/// <summary> /// <summary>
/// Layout of the buttons which should be displayed always on top. /// Layout of the buttons which should be displayed always on top.
/// </summary> /// </summary>
public List<ButtonBase> HeadLayoutButtonRow { get; set; } public ButtonRow HeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// Layout of columns which should be displayed below the header /// Layout of columns which should be displayed below the header
/// </summary> /// </summary>
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; } public ButtonRow SubHeadLayoutButtonRow { get; set; }
/// <summary>
/// Layout of columns which should be displayed below the header
/// </summary>
private ButtonRow TagsSubHeadLayoutButtonRow { get; set; }
/// <summary> /// <summary>
/// List of Tags which will be allowed to filter by. /// List of Tags which will be allowed to filter by.
@ -134,7 +166,7 @@ namespace TelegramBotBase.Controls.Hybrid
public TaggedButtonGrid() public TaggedButtonGrid()
{ {
this.ButtonsForm = new ButtonForm(); this.DataSource = new ButtonFormDataSource();
this.SelectedViewIndex = 0; this.SelectedViewIndex = 0;
} }
@ -147,7 +179,7 @@ namespace TelegramBotBase.Controls.Hybrid
public TaggedButtonGrid(ButtonForm form) public TaggedButtonGrid(ButtonForm form)
{ {
this.ButtonsForm = form; this.DataSource = new ButtonFormDataSource(form);
} }
@ -202,27 +234,60 @@ namespace TelegramBotBase.Controls.Hybrid
if (result.MessageText == null || result.MessageText == "") if (result.MessageText == null || result.MessageText == "")
return; return;
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) var matches = new List<ButtonRow>();
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText) ButtonRow match = null;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText); int index = -1;
if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
match = HeadLayoutButtonRow;
goto check;
}
if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
match = SubHeadLayoutButtonRow;
goto check;
}
if (TagsSubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
match = TagsSubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.MessageText);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
//var index = bf.FindRowByButton(button);
check:
var index = ButtonsForm.FindRowByButton(button);
switch (this.SelectedViewIndex) switch (this.SelectedViewIndex)
{ {
case 0: case 0:
if (button != null) //Remove button click message
{ if (this.DeleteReplyMessage)
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); await Device.DeleteMessage(result.MessageId);
//Remove button click message if (match != null)
if (this.DeleteReplyMessage) {
await Device.DeleteMessage(result.MessageId); await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
result.Handled = true; result.Handled = true;
return; return;
} }
@ -287,17 +352,25 @@ namespace TelegramBotBase.Controls.Hybrid
break; break;
case 1: case 1:
//Remove button click message
if (this.DeleteReplyMessage)
await Device.DeleteMessage(result.MessageId);
if (result.MessageText == this.BackLabel) if (result.MessageText == this.BackLabel)
{ {
//Remove button click message
if (this.DeletePreviousMessage)
await Device.DeleteMessage(result.MessageId);
this.SelectedViewIndex = 0; this.SelectedViewIndex = 0;
this.Updated(); this.Updated();
result.Handled = true; result.Handled = true;
return; return;
} }
else if (result.MessageText == this.CheckAllLabel)
{
this.CheckAllTags();
}
else if (result.MessageText == this.UncheckAllLabel)
{
this.UncheckAllTags();
}
var i = result.MessageText.LastIndexOf(" "); var i = result.MessageText.LastIndexOf(" ");
if (i == -1) if (i == -1)
@ -340,15 +413,48 @@ namespace TelegramBotBase.Controls.Hybrid
await result.ConfirmAction(this.ConfirmationText ?? ""); await result.ConfirmAction(this.ConfirmationText ?? "");
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) ButtonRow match = null;
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) int index = -1;
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
var index = ButtonsForm.FindRowByButton(button); if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
if (button != null)
{ {
await OnButtonClicked(new ButtonClickedEventArgs(button, index)); match = HeadLayoutButtonRow;
goto check;
}
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
match = SubHeadLayoutButtonRow;
goto check;
}
if (TagsSubHeadLayoutButtonRow?.Matches(result.RawData) ?? false)
{
match = TagsSubHeadLayoutButtonRow;
goto check;
}
var br = DataSource.FindRow(result.RawData, false);
if (br != null)
{
match = br.Item1;
index = br.Item2;
}
//var bf = DataSource.ButtonForm;
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
//var index = bf.FindRowByButton(button);
check:
if (match != null)
{
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
result.Handled = true; result.Handled = true;
return; return;
@ -386,6 +492,18 @@ namespace TelegramBotBase.Controls.Hybrid
this.SelectedViewIndex = 0; this.SelectedViewIndex = 0;
this.Updated(); this.Updated();
break;
case "$checkall$":
this.CheckAllTags();
break;
case "$uncheckall$":
this.UncheckAllTags();
break; break;
} }
@ -400,28 +518,28 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
case eKeyboardType.InlineKeyBoard: case eKeyboardType.InlineKeyBoard:
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
} }
break; break;
case eKeyboardType.ReplyKeyboard: case eKeyboardType.ReplyKeyboard:
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging) if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
{ {
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows }; throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
} }
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols) if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
{ {
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols }; throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
} }
break; break;
@ -468,16 +586,16 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
Message m = null; Message m = null;
ButtonForm form = this.ButtonsForm; ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, (this.EnableSearch ? this.SearchQuery : null));
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
{ //{
form = form.FilterDuplicate(this.SearchQuery, true); // form = form.FilterDuplicate(this.SearchQuery, true);
} //}
else //else
{ //{
form = form.Duplicate(); // form = form.Duplicate();
} //}
if (this.Tags != null && this.SelectedTags != null) if (this.Tags != null && this.SelectedTags != null)
{ {
@ -486,23 +604,23 @@ namespace TelegramBotBase.Controls.Hybrid
if (this.EnablePaging) if (this.EnablePaging)
{ {
form = GeneratePagingView(form); IntegratePagingView(form);
} }
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0) if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
{ {
form.InsertButtonRow(0, this.HeadLayoutButtonRow); form.InsertButtonRow(0, this.HeadLayoutButtonRow.ToArray());
} }
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0) if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
{ {
if (this.IsNavigationBarVisible) if (this.IsNavigationBarVisible)
{ {
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow); form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
} }
else else
{ {
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow); form.InsertButtonRow(1, this.SubHeadLayoutButtonRow.ToArray());
} }
} }
@ -559,52 +677,37 @@ namespace TelegramBotBase.Controls.Hybrid
} }
} }
private ButtonForm GeneratePagingView(ButtonForm dataForm) private void IntegratePagingView(ButtonForm dataForm)
{ {
ButtonForm bf = new ButtonForm();
for (int i = 0; i < this.MaximumRow - LayoutRows; i++)
{
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
if (it > dataForm.Rows - 1)
break;
bf.AddButtonRow(dataForm[it]);
}
//No Items //No Items
if (this.ButtonsForm.Count == 0) if (dataForm.Rows == 0)
{ {
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$")); dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
} }
if (this.IsNavigationBarVisible) if (this.IsNavigationBarVisible)
{ {
//🔍 //🔍
List<ButtonBase> lst = new List<ButtonBase>(); ButtonRow row = new ButtonRow();
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$")); row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$")); row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
if (this.Tags != null && this.Tags.Count > 0) if (this.Tags != null && this.Tags.Count > 0)
{ {
lst.Add(new ButtonBase("📁", "$filter$")); row.Add(new ButtonBase("📁", "$filter$"));
} }
lst.Add(new ButtonBase(NextPageLabel, "$next$")); row.Add(new ButtonBase(NextPageLabel, "$next$"));
if (this.EnableSearch) if (this.EnableSearch)
{ {
lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$")); row.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
} }
bf.InsertButtonRow(0, lst); dataForm.InsertButtonRow(0, row);
bf.AddButtonRow(lst); dataForm.AddButtonRow(row);
} }
return bf;
} }
#endregion #endregion
@ -620,6 +723,12 @@ namespace TelegramBotBase.Controls.Hybrid
bf.AddButtonRow(this.BackLabel, "$back$"); bf.AddButtonRow(this.BackLabel, "$back$");
if (EnableCheckAllTools)
{
this.TagsSubHeadLayoutButtonRow = new ButtonRow(new ButtonBase(CheckAllLabel, "$checkall$"), new ButtonBase(UncheckAllLabel, "$uncheckall$"));
bf.AddButtonRow(TagsSubHeadLayoutButtonRow);
}
foreach (var t in this.Tags) foreach (var t in this.Tags)
{ {
@ -748,7 +857,7 @@ namespace TelegramBotBase.Controls.Hybrid
{ {
get get
{ {
return this.LayoutRows + ButtonsForm.Rows; return this.LayoutRows + DataSource.RowCount;
} }
} }
@ -771,28 +880,46 @@ namespace TelegramBotBase.Controls.Hybrid
if (this.SubHeadLayoutButtonRow != null && this.SubHeadLayoutButtonRow.Count > 0) if (this.SubHeadLayoutButtonRow != null && this.SubHeadLayoutButtonRow.Count > 0)
layoutRows++; layoutRows++;
if (EnableCheckAllTools && this.SelectedViewIndex == 1)
{
layoutRows++;
}
return layoutRows; return layoutRows;
} }
} }
/// <summary>
/// Returns the number of item rows per page.
/// </summary>
public int ItemRowsPerPage
{
get
{
return this.MaximumRow - this.LayoutRows;
}
}
public int PageCount public int PageCount
{ {
get get
{ {
if (this.ButtonsForm.Count == 0) if (DataSource.RowCount == 0)
return 1; return 1;
var bf = this.ButtonsForm; //var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "") var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
{
bf = bf.FilterDuplicate(this.SearchQuery);
}
if (bf.Rows == 0) //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
//{
// bf = bf.FilterDuplicate(this.SearchQuery);
//}
if (max == 0)
return 1; return 1;
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows))); return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
} }
} }
@ -844,6 +971,8 @@ namespace TelegramBotBase.Controls.Hybrid
break; break;
} }
}
/// <summary> /// <summary>
/// Checks all tags for filtering. /// Checks all tags for filtering.

View File

@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Datasources
{
public class ButtonFormDataSource : Interfaces.IDataSource<ButtonRow>
{
public virtual ButtonForm ButtonForm
{
get
{
return __buttonform;
}
set
{
__buttonform = value;
}
}
private ButtonForm __buttonform = null;
public ButtonFormDataSource()
{
__buttonform = new ButtonForm();
}
public ButtonFormDataSource(ButtonForm bf)
{
__buttonform = bf;
}
/// <summary>
/// Returns the amount of rows exisiting.
/// </summary>
/// <returns></returns>
public virtual int Count => ButtonForm.Count;
/// <summary>
/// Returns the amount of rows.
/// </summary>
public virtual int RowCount => ButtonForm.Rows;
/// <summary>
/// Returns the maximum amount of columns.
/// </summary>
public virtual int ColumnCount => ButtonForm.Cols;
/// <summary>
/// Returns the row with the specific index.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public virtual ButtonRow ItemAt(int index)
{
return ButtonForm[index];
}
public virtual List<ButtonRow> ItemRange(int start, int count)
{
return ButtonForm.GetRange(start, count);
}
public virtual List<ButtonRow> AllItems()
{
return ButtonForm.ToArray();
}
public virtual ButtonForm PickItems(int start, int count, String filter = null)
{
ButtonForm bf = new ButtonForm();
ButtonForm dataForm = null;
if (filter == null)
{
dataForm = ButtonForm.Duplicate();
}
else
{
dataForm = ButtonForm.FilterDuplicate(filter, true);
}
for (int i = 0; i < count; i++)
{
int it = start + i;
if (it > dataForm.Rows - 1)
break;
bf.AddButtonRow(dataForm[it]);
}
return bf;
}
public virtual ButtonForm PickAllItems(String filter = null)
{
if (filter == null)
return ButtonForm.Duplicate();
return ButtonForm.FilterDuplicate(filter, true);
}
public virtual Tuple<ButtonRow, int> FindRow(String text, bool useText = true)
{
return ButtonForm.FindRow(text, useText);
}
/// <summary>
/// Returns the maximum items of this data source.
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
public virtual int CalculateMax(String filter = null)
{
return PickAllItems(filter).Rows;
}
public virtual ButtonRow Render(object data)
{
return data as ButtonRow;
}
public static implicit operator ButtonFormDataSource(ButtonForm bf)
{
return new ButtonFormDataSource(bf);
}
public static implicit operator ButtonForm(ButtonFormDataSource ds)
{
return ds.ButtonForm;
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TelegramBotBase.Datasources
{
public class StaticDataSource<T> : Interfaces.IDataSource<T>
{
List<T> Data { get; set; }
public StaticDataSource()
{
}
public StaticDataSource(List<T> data)
{
this.Data = data;
}
public int Count
{
get
{
return Data.Count;
}
}
public T ItemAt(int index)
{
return Data[index];
}
public List<T> ItemRange(int start, int count)
{
return Data.Skip(start).Take(count).ToList();
}
public List<T> AllItems()
{
return Data;
}
}
}

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
namespace TelegramBotBase.Form namespace TelegramBotBase.Form
{ {
@ -13,7 +14,7 @@ namespace TelegramBotBase.Form
/// </summary> /// </summary>
public class ButtonForm public class ButtonForm
{ {
List<List<ButtonBase>> Buttons = new List<List<ButtonBase>>(); List<ButtonRow> Buttons = new List<ButtonRow>();
public IReplyMarkup Markup { get; set; } public IReplyMarkup Markup { get; set; }
@ -43,7 +44,7 @@ namespace TelegramBotBase.Form
} }
public List<ButtonBase> this[int row] public ButtonRow this[int row]
{ {
get get
{ {
@ -66,9 +67,14 @@ namespace TelegramBotBase.Form
Buttons.Add(new List<ButtonBase>() { new ButtonBase(Text, Value, Url) }); Buttons.Add(new List<ButtonBase>() { new ButtonBase(Text, Value, Url) });
} }
public void AddButtonRow(IEnumerable<ButtonBase> row) //public void AddButtonRow(ButtonRow row)
//{
// Buttons.Add(row.ToList());
//}
public void AddButtonRow(ButtonRow row)
{ {
Buttons.Add(row.ToList()); Buttons.Add(row);
} }
public void AddButtonRow(params ButtonBase[] row) public void AddButtonRow(params ButtonBase[] row)
@ -76,16 +82,26 @@ namespace TelegramBotBase.Form
AddButtonRow(row.ToList()); AddButtonRow(row.ToList());
} }
public void AddButtonRows(IEnumerable<ButtonRow> rows)
{
Buttons.AddRange(rows);
}
public void InsertButtonRow(int index, IEnumerable<ButtonBase> row) public void InsertButtonRow(int index, IEnumerable<ButtonBase> row)
{ {
Buttons.Insert(index, row.ToList()); Buttons.Insert(index, row.ToList());
} }
public void InsertButtonRow(int index, params ButtonBase[] row) public void InsertButtonRow(int index, ButtonRow row)
{ {
InsertButtonRow(index, row.ToList()); Buttons.Insert(index, row);
} }
//public void InsertButtonRow(int index, params ButtonBase[] row)
//{
// InsertButtonRow(index, row.ToList());
//}
public static T[][] SplitTo<T>(IEnumerable<T> items, int itemsPerRow = 2) public static T[][] SplitTo<T>(IEnumerable<T> items, int itemsPerRow = 2)
{ {
T[][] splitted = default(T[][]); T[][] splitted = default(T[][]);
@ -132,34 +148,62 @@ namespace TelegramBotBase.Form
} }
} }
/// <summary>
/// Returns a range of rows from the buttons.
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <returns></returns>
public List<ButtonRow> GetRange(int start, int count)
{
return Buttons.Skip(start).Take(count).ToList();
}
public List<ButtonBase> ToList() public List<ButtonBase> ToList()
{ {
return this.Buttons.DefaultIfEmpty(new List<ButtonBase>()).Aggregate((a, b) => a.Union(b).ToList()); return this.Buttons.DefaultIfEmpty(new List<ButtonBase>()).Select(a => a.ToList()).Aggregate((a, b) => a.Union(b).ToList());
} }
public InlineKeyboardButton[][] ToInlineButtonArray() public InlineKeyboardButton[][] ToInlineButtonArray()
{ {
var ikb = this.Buttons.Select(a => a.Select(b => b.ToInlineButton(this)).ToArray()).ToArray(); var ikb = this.Buttons.Select(a => a.ToArray().Select(b => b.ToInlineButton(this)).ToArray()).ToArray();
return ikb; return ikb;
} }
public KeyboardButton[][] ToReplyButtonArray() public KeyboardButton[][] ToReplyButtonArray()
{ {
var ikb = this.Buttons.Select(a => a.Select(b => b.ToKeyboardButton(this)).ToArray()).ToArray(); var ikb = this.Buttons.Select(a => a.ToArray().Select(b => b.ToKeyboardButton(this)).ToArray()).ToArray();
return ikb; return ikb;
} }
public List<ButtonRow> ToArray()
{
return Buttons;
}
public int FindRowByButton(ButtonBase button) public int FindRowByButton(ButtonBase button)
{ {
var row = this.Buttons.FirstOrDefault(a => a.Count(b => b == button) > 0); var row = this.Buttons.FirstOrDefault(a => a.ToArray().Count(b => b == button) > 0);
if (row == null) if (row == null)
return -1; return -1;
return this.Buttons.IndexOf(row); return this.Buttons.IndexOf(row);
} }
public Tuple<ButtonRow, int> FindRow(String text, bool useText = true)
{
var r = this.Buttons.FirstOrDefault(a => a.Matches(text, useText));
if (r == null)
return null;
var i = this.Buttons.IndexOf(r);
return new Tuple<ButtonRow, int>(r, i);
}
/// <summary> /// <summary>
/// Returns the first Button with the given value. /// Returns the first Button with the given value.
/// </summary> /// </summary>
@ -204,7 +248,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons) foreach (var b in Buttons)
{ {
var lst = new List<ButtonBase>(); var lst = new ButtonRow();
foreach (var b2 in b) foreach (var b2 in b)
{ {
lst.Add(b2); lst.Add(b2);
@ -229,7 +273,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons) foreach (var b in Buttons)
{ {
var lst = new List<ButtonBase>(); var lst = new ButtonRow();
foreach (var b2 in b) foreach (var b2 in b)
{ {
if (b2.Text.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1) if (b2.Text.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1)
@ -238,7 +282,7 @@ namespace TelegramBotBase.Form
//Copy full row, when at least one match has found. //Copy full row, when at least one match has found.
if (ByRow) if (ByRow)
{ {
lst.AddRange(b); lst = b;
break; break;
} }
else else
@ -268,7 +312,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons) foreach (var b in Buttons)
{ {
var lst = new List<ButtonBase>(); var lst = new ButtonRow();
foreach (var b2 in b) foreach (var b2 in b)
{ {
if (!(b2 is TagButtonBase tb)) if (!(b2 is TagButtonBase tb))
@ -280,7 +324,7 @@ namespace TelegramBotBase.Form
//Copy full row, when at least one match has found. //Copy full row, when at least one match has found.
if (ByRow) if (ByRow)
{ {
lst.AddRange(b); lst = b;
break; break;
} }
else else

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Controls.Hybrid;
namespace TelegramBotBase.Interfaces
{
public interface IDataSource<T>
{
/// <summary>
/// Returns the amount of items within this source.
/// </summary>
/// <returns></returns>
int Count { get; }
/// <summary>
/// Returns the item at the specific index.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
T ItemAt(int index);
/// <summary>
/// Get all items from this source within this range.
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <returns></returns>
List<T> ItemRange(int start, int count);
/// <summary>
/// Gets a list of all items of this datasource.
/// </summary>
/// <returns></returns>
List<T> AllItems();
}
}

View File

@ -33,6 +33,7 @@ namespace TelegramBotBaseTest.Tests.Controls
m_Buttons.HeadLayoutButtonRow = new List<ButtonBase>() { new ButtonBase("Back", "back") }; m_Buttons.HeadLayoutButtonRow = new List<ButtonBase>() { new ButtonBase("Back", "back") };
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures); var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
ButtonForm bf = new ButtonForm(); ButtonForm bf = new ButtonForm();
@ -45,7 +46,9 @@ namespace TelegramBotBaseTest.Tests.Controls
m_Buttons.Tags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList(); m_Buttons.Tags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
m_Buttons.SelectedTags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList(); m_Buttons.SelectedTags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
m_Buttons.ButtonsForm = bf; m_Buttons.EnableCheckAllTools = true;
m_Buttons.DataSource = new TelegramBotBase.Datasources.ButtonFormDataSource(bf);
m_Buttons.ButtonClicked += Bg_ButtonClicked; m_Buttons.ButtonClicked += Bg_ButtonClicked;
@ -57,11 +60,13 @@ namespace TelegramBotBaseTest.Tests.Controls
if (e.Button == null) if (e.Button == null)
return; return;
if (e.Button.Value == "back") switch (e.Button.Value)
{ {
var start = new Menu();
await this.NavigateTo(start); case "back":
return; var start = new Menu();
await this.NavigateTo(start);
return;
} }

View File

@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Datasources;
using TelegramBotBase.Form;
namespace TelegramBotBaseTest.Tests.Datasources
{
public class CustomDataSource : ButtonFormDataSource
{
public List<String> Countries = new List<string>() { "Country 1", "Country 2", "Country 3" };
public CustomDataSource()
{
loadData();
}
/// <summary>
/// This method has the example purpose of creating and loading some example data.
/// When using a database you do not need this kind of method.
/// </summary>
private void loadData()
{
//Exists data source? Read it
if (File.Exists(AppContext.BaseDirectory + "countries.json"))
{
try
{
var List = Newtonsoft.Json.JsonConvert.DeserializeObject<List<String>>(File.ReadAllText("countries.json"));
Countries = List;
}
catch
{
}
return;
}
//If not, create it
try
{
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures).Select(a => a.DisplayName).ToList();
Countries = countries;
var tmp = Newtonsoft.Json.JsonConvert.SerializeObject(countries);
File.WriteAllText( AppContext.BaseDirectory + "countries.json", tmp);
}
catch
{
}
}
public override ButtonRow ItemAt(int index)
{
var item = Countries.ElementAt(index);
if (item == null)
return new ButtonRow();
return Render(item);
}
public override List<ButtonRow> ItemRange(int start, int count)
{
var items = Countries.Skip(start).Take(count);
List<ButtonRow> lst = new List<ButtonRow>();
foreach (var c in items)
{
lst.Add(Render(c));
}
return lst;
}
public override List<ButtonRow> AllItems()
{
List<ButtonRow> lst = new List<ButtonRow>();
foreach (var c in Countries)
{
lst.Add(Render(c));
}
return lst;
}
public override ButtonForm PickItems(int start, int count, string filter = null)
{
List<ButtonRow> rows = ItemRange(start, count);
ButtonForm lst = new ButtonForm();
foreach (var c in rows)
{
lst.AddButtonRow(c);
}
return lst;
}
public override ButtonForm PickAllItems(string filter = null)
{
List<ButtonRow> rows = AllItems();
ButtonForm bf = new ButtonForm();
bf.AddButtonRows(rows);
return bf;
}
public override int CalculateMax(string filter = null)
{
if (filter == null)
return Countries.Count;
return Countries.Where(a => a.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) != -1).Count();
}
public override ButtonRow Render(object data)
{
var s = data as String;
if (s == null)
return new ButtonRow(new ButtonBase("Empty", "zero"));
return new ButtonRow(new ButtonBase(s, s));
}
public override int Count
{
get
{
return Countries.Count;
}
}
public override int ColumnCount
{
get
{
return 1;
}
}
public override int RowCount
{
get
{
return this.Count;
}
}
}
}

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace TelegramBotBaseTest.Tests.Datasources
{
public class List : FormBase
{
ButtonGrid __buttons = null;
public List()
{
this.Init += List_Init;
}
private async Task List_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
__buttons = new ButtonGrid();
__buttons.EnablePaging = true;
__buttons.EnableSearch = false;
__buttons.ButtonClicked += __buttons_ButtonClicked;
__buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard;
__buttons.DeleteReplyMessage = true;
__buttons.HeadLayoutButtonRow = new ButtonRow(new ButtonBase("Back", "back"));
var cds = new CustomDataSource();
__buttons.DataSource = cds;
AddControl(__buttons);
}
private async Task __buttons_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
switch(e.Button.Value)
{
case "back":
var mn = new Menu();
await NavigateTo(mn);
break;
}
}
public override async Task Load(MessageResult message)
{
}
public override async Task Render(MessageResult message)
{
}
}
}

View File

@ -190,6 +190,14 @@ namespace TelegramBotBaseTest.Tests
await NavigateTo(nc); await NavigateTo(nc);
break;
case "dynamicbuttongrid":
var dg = new Datasources.List();
await NavigateTo(dg);
break; break;
default: default:
@ -237,6 +245,8 @@ namespace TelegramBotBaseTest.Tests
btn.AddButtonRow(new ButtonBase("#17 NavigationController (Push/Pop)", new CallbackData("a", "navigationcontroller").Serialize())); btn.AddButtonRow(new ButtonBase("#17 NavigationController (Push/Pop)", new CallbackData("a", "navigationcontroller").Serialize()));
btn.AddButtonRow(new ButtonBase("#18 Dynamic ButtonGrid (DataSources)", new CallbackData("a", "dynamicbuttongrid").Serialize()));
await this.Device.Send("Choose your test:", btn); await this.Device.Send("Choose your test:", btn);
} }