diff --git a/TelegramBotBase/Args/ButtonClickedEventArgs.cs b/TelegramBotBase/Args/ButtonClickedEventArgs.cs
index a99b9f8..ef9ef71 100644
--- a/TelegramBotBase/Args/ButtonClickedEventArgs.cs
+++ b/TelegramBotBase/Args/ButtonClickedEventArgs.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace TelegramBotBase.Args
@@ -18,6 +19,8 @@ namespace TelegramBotBase.Args
public object Tag { get; set; }
+ public ButtonRow Row { get; set; }
+
public ButtonClickedEventArgs()
{
@@ -36,5 +39,11 @@ namespace TelegramBotBase.Args
this.Index = Index;
}
+ public ButtonClickedEventArgs(ButtonBase button, int Index, ButtonRow row)
+ {
+ this.Button = button;
+ this.Index = Index;
+ this.Row = row;
+ }
}
}
diff --git a/TelegramBotBase/Args/CheckedChangedEventArgs.cs b/TelegramBotBase/Args/CheckedChangedEventArgs.cs
index 90d4014..4750334 100644
--- a/TelegramBotBase/Args/CheckedChangedEventArgs.cs
+++ b/TelegramBotBase/Args/CheckedChangedEventArgs.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
+using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace TelegramBotBase.Args
@@ -17,7 +18,7 @@ namespace TelegramBotBase.Args
///
/// Contains all buttons within this row, excluding the checkbox.
///
- public List Row { get; set; }
+ public ButtonRow Row { get; set; }
///
@@ -31,7 +32,7 @@ namespace TelegramBotBase.Args
}
- public CheckedChangedEventArgs(List row, int Index, bool Checked)
+ public CheckedChangedEventArgs(ButtonRow row, int Index, bool Checked)
{
this.Row = row;
this.Index = Index;
diff --git a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs
index fb116c7..d8bfdb1 100644
--- a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs
+++ b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs
@@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
+using TelegramBotBase.Datasources;
using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions;
using TelegramBotBase.Form;
@@ -30,7 +31,26 @@ namespace TelegramBotBase.Controls.Hybrid
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);
+ }
+ }
+
+ ///
+ /// Data source of the items.
+ ///
+ public ButtonFormDataSource DataSource { get; set; }
public int? MessageId { get; set; }
@@ -89,12 +109,12 @@ namespace TelegramBotBase.Controls.Hybrid
///
/// Layout of the buttons which should be displayed always on top.
///
- public List HeadLayoutButtonRow { get; set; }
+ public ButtonRow HeadLayoutButtonRow { get; set; }
///
/// Layout of columns which should be displayed below the header
///
- public List SubHeadLayoutButtonRow { get; set; }
+ public ButtonRow SubHeadLayoutButtonRow { get; set; }
///
/// Defines which type of Button Keyboard should be rendered.
@@ -123,8 +143,7 @@ namespace TelegramBotBase.Controls.Hybrid
public ButtonGrid()
{
- this.ButtonsForm = new ButtonForm();
-
+ this.DataSource = new ButtonFormDataSource();
}
@@ -136,7 +155,7 @@ namespace TelegramBotBase.Controls.Hybrid
public ButtonGrid(ButtonForm form)
{
- this.ButtonsForm = form;
+ this.DataSource = new ButtonFormDataSource(form);
}
@@ -188,22 +207,49 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler)
return;
- if (result.MessageText == null)
+ if (result.MessageText == null || result.MessageText == "")
return;
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
+ var matches = new List();
+ ButtonRow match = null;
+ int index = -1;
- var index = ButtonsForm.FindRowByButton(button);
-
- if (button != null)
+ if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
{
- await OnButtonClicked(new ButtonClickedEventArgs(button, index));
+ match = HeadLayoutButtonRow;
+ goto check;
+ }
- //Remove button click message
- if (this.DeleteReplyMessage)
- await Device.DeleteMessage(result.MessageId);
+ 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)
+ {
+ await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
result.Handled = true;
return;
@@ -261,22 +307,48 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler)
return;
- await result.ConfirmAction(this.ConfirmationText ?? "");
-
//Find clicked button depending on Text or Value (depending on markup type)
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
return;
+ await result.ConfirmAction(this.ConfirmationText ?? "");
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
+ ButtonRow match = null;
+ int index = -1;
- var index = ButtonsForm.FindRowByButton(button);
-
- if (button != null)
+ if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
- 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;
return;
@@ -313,28 +385,28 @@ namespace TelegramBotBase.Controls.Hybrid
{
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;
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;
@@ -351,22 +423,21 @@ namespace TelegramBotBase.Controls.Hybrid
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 != "")
- {
- form = form.FilterDuplicate(this.SearchQuery, true);
- }
- else
- {
- form = form.Duplicate();
- }
+ //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
+ //{
+ // form = form.FilterDuplicate(this.SearchQuery, true);
+ //}
+ //else
+ //{
+ // form = form.Duplicate();
+ //}
if (this.EnablePaging)
{
- form = GeneratePagingView(form);
+ IntegratePagingView(form);
}
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
@@ -386,26 +457,37 @@ namespace TelegramBotBase.Controls.Hybrid
}
}
+ Message m = null;
+
switch (this.KeyboardType)
{
//Reply Keyboard could only be updated with a new keyboard.
case eKeyboardType.ReplyKeyboard:
- if (this.MessageId != null)
+
+ if (form.Count == 0)
{
- if (form.Count == 0)
+ if (this.MessageId != null)
{
await this.Device.HideReplyKeyboard();
this.MessageId = null;
- return;
}
- if (this.DeletePreviousMessage)
- await this.Device.DeleteMessage(this.MessageId.Value);
+ return;
}
- if (form.Count == 0)
- return;
+ //if (this.MessageId != null)
+ //{
+ // if (form.Count == 0)
+ // {
+ // await this.Device.HideReplyKeyboard();
+ // this.MessageId = null;
+ // return;
+ // }
+ //}
+
+ //if (form.Count == 0)
+ // return;
var rkm = (ReplyKeyboardMarkup)form;
@@ -413,6 +495,10 @@ namespace TelegramBotBase.Controls.Hybrid
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
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;
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
- if (this.ButtonsForm.Count == 0)
+ if (dataForm.Rows == 0)
{
- bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
+ dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
}
if (this.IsNavigationBarVisible)
{
//🔍
- List lst = new List();
- lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
- lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
- lst.Add(new ButtonBase(NextPageLabel, "$next$"));
+ ButtonRow row = new ButtonRow();
+ row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
+ row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
+ row.Add(new ButtonBase(NextPageLabel, "$next$"));
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
@@ -545,7 +615,7 @@ namespace TelegramBotBase.Controls.Hybrid
{
get
{
- return this.LayoutRows + ButtonsForm.Rows;
+ return this.LayoutRows + DataSource.RowCount;
}
}
@@ -572,24 +642,40 @@ namespace TelegramBotBase.Controls.Hybrid
}
}
+ ///
+ /// Returns the number of item rows per page.
+ ///
+ public int ItemRowsPerPage
+ {
+ get
+ {
+ return this.MaximumRow - this.LayoutRows;
+ }
+ }
+
+ ///
+ /// Return the number of pages.
+ ///
public int PageCount
{
get
{
- if (this.ButtonsForm.Count == 0)
+ if (DataSource.RowCount == 0)
return 1;
- var bf = this.ButtonsForm;
+ //var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
- if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
- {
- bf = bf.FilterDuplicate(this.SearchQuery);
- }
+ var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
- if (bf.Rows == 0)
+ //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
+ //{
+ // bf = bf.FilterDuplicate(this.SearchQuery);
+ //}
+
+ if (max == 0)
return 1;
- return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows)));
+ return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
}
}
diff --git a/TelegramBotBase/Controls/Hybrid/ButtonRow.cs b/TelegramBotBase/Controls/Hybrid/ButtonRow.cs
new file mode 100644
index 0000000..2d0deab
--- /dev/null
+++ b/TelegramBotBase/Controls/Hybrid/ButtonRow.cs
@@ -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 __buttons = new List();
+
+ 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 GetEnumerator()
+ {
+ return __buttons.GetEnumerator();
+ }
+
+ public ButtonBase[] ToArray()
+ {
+ return __buttons.ToArray();
+ }
+
+ public List 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;
+ }
+
+ ///
+ /// Returns the button inside of the row which matches.
+ ///
+ ///
+ ///
+ ///
+ 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 list)
+ {
+ return new ButtonRow() { __buttons = list };
+ }
+ }
+}
diff --git a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs
index fe3b8c9..9c2e414 100644
--- a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs
+++ b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs
@@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
+using TelegramBotBase.Datasources;
using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions;
using TelegramBotBase.Form;
@@ -32,7 +33,23 @@ namespace TelegramBotBase.Controls.Hybrid
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);
+ }
+ }
+
+ ///
+ /// Data source of the items.
+ ///
+ public ButtonFormDataSource DataSource { get; set; }
List CheckedRows { get; set; } = new List();
@@ -51,6 +68,11 @@ namespace TelegramBotBase.Controls.Hybrid
public bool DeletePreviousMessage { get; set; } = true;
+ ///
+ /// Removes the reply message from a user.
+ ///
+ public bool DeleteReplyMessage { get; set; } = true;
+
///
/// Parsemode of the message.
///
@@ -92,12 +114,12 @@ namespace TelegramBotBase.Controls.Hybrid
///
/// Layout of the buttons which should be displayed always on top.
///
- public List HeadLayoutButtonRow { get; set; }
+ public ButtonRow HeadLayoutButtonRow { get; set; }
///
/// Layout of columns which should be displayed below the header
///
- public List SubHeadLayoutButtonRow { get; set; }
+ public ButtonRow SubHeadLayoutButtonRow { get; set; }
///
/// Defines which type of Button Keyboard should be rendered.
@@ -126,7 +148,7 @@ namespace TelegramBotBase.Controls.Hybrid
public CheckedButtonList()
{
- this.ButtonsForm = new ButtonForm();
+ this.DataSource = new ButtonFormDataSource();
}
@@ -139,7 +161,7 @@ namespace TelegramBotBase.Controls.Hybrid
public CheckedButtonList(ButtonForm form)
{
- this.ButtonsForm = form;
+ this.DataSource = new ButtonFormDataSource(form);
}
public event AsyncEventHandler ButtonClicked
@@ -198,16 +220,50 @@ namespace TelegramBotBase.Controls.Hybrid
if (!result.IsFirstHandler)
return;
- if (result.MessageText == null)
+ if (result.MessageText == null || result.MessageText == "")
return;
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
+ var matches = new List();
+ ButtonRow match = null;
+ 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)
{
@@ -226,7 +282,7 @@ namespace TelegramBotBase.Controls.Hybrid
else if (result.MessageText.EndsWith(CheckedIconLabel))
{
var s = result.MessageText.Split(' ', '.');
- index = int.Parse(s[0]);
+ index = int.Parse(s[0]) - 1;
if (!this.CheckedRows.Contains(index))
return;
@@ -241,7 +297,7 @@ namespace TelegramBotBase.Controls.Hybrid
else if (result.MessageText.EndsWith(UncheckedIconLabel))
{
var s = result.MessageText.Split(' ', '.');
- index = int.Parse(s[0]);
+ index = int.Parse(s[0]) - 1;
if (this.CheckedRows.Contains(index))
return;
@@ -285,14 +341,18 @@ namespace TelegramBotBase.Controls.Hybrid
}
- await OnButtonClicked(new ButtonClickedEventArgs(button, index));
-
- //Remove button click message
- if (this.DeletePreviousMessage)
- await Device.DeleteMessage(result.MessageId);
+ await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
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)
@@ -309,20 +369,55 @@ namespace TelegramBotBase.Controls.Hybrid
await result.ConfirmAction(this.ConfirmationText ?? "");
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
+ ButtonRow match = null;
+ int index = -1;
- var index = ButtonsForm.FindRowByButton(button);
-
- if (button != null)
+ if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
- 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;
return;
}
+ //if (button != null)
+ //{
+ // await OnButtonClicked(new ButtonClickedEventArgs(button, index));
+
+ // result.Handled = true;
+ // return;
+ //}
+
switch (result.RawData)
{
case "$previous$":
@@ -396,28 +491,28 @@ namespace TelegramBotBase.Controls.Hybrid
{
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;
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;
@@ -436,7 +531,7 @@ namespace TelegramBotBase.Controls.Hybrid
Message m = null;
- ButtonForm form = this.ButtonsForm;
+ ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, null);
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
//{
@@ -444,12 +539,12 @@ namespace TelegramBotBase.Controls.Hybrid
//}
//else
//{
- form = form.Duplicate();
+ //form = form.Duplicate();
//}
if (this.EnablePaging)
{
- form = GeneratePagingView(form);
+ IntegratePagingView(form);
}
else
{
@@ -458,18 +553,18 @@ namespace TelegramBotBase.Controls.Hybrid
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.IsNavigationBarVisible)
{
- form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
+ form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
}
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.
case eKeyboardType.ReplyKeyboard:
- if (this.MessageId != null)
+ if (form.Count == 0)
{
- if (form.Count == 0)
+ if (this.MessageId != null)
{
await this.Device.HideReplyKeyboard();
this.MessageId = null;
- return;
}
- if (this.DeletePreviousMessage)
- await this.Device.DeleteMessage(this.MessageId.Value);
+ return;
}
- if (form.Count == 0)
- return;
+ //if (form.Count == 0)
+ // return;
var rkm = (ReplyKeyboardMarkup)form;
@@ -500,6 +593,10 @@ namespace TelegramBotBase.Controls.Hybrid
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
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;
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();
bf = PrepareCheckableLayout(dataForm);
- //No Items
- if (this.ButtonsForm.Count == 0)
- {
- bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
- }
if (this.IsNavigationBarVisible)
{
//🔍
- List lst = new List();
- lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
- lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
- lst.Add(new ButtonBase(NextPageLabel, "$next$"));
+ ButtonRow row = new ButtonRow();
+ row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
+ row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
+ 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)
{
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;
- if (it > dataForm.Rows - 1)
- break;
+ //if (it > dataForm.Rows - 1)
+ // break;
- var r = dataForm[it];
+ var r = dataForm[i];
String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel;
//On reply keyboards we need a unique text.
if (this.KeyboardType == eKeyboardType.ReplyKeyboard)
{
- s = $"{it}. " + s;
+ s = $"{it + 1}. " + s;
}
if (CheckedRows.Contains(it))
@@ -652,7 +743,7 @@ namespace TelegramBotBase.Controls.Hybrid
{
get
{
- return this.LayoutRows + ButtonsForm.Rows;
+ return this.LayoutRows + DataSource.RowCount;
}
}
@@ -679,24 +770,37 @@ namespace TelegramBotBase.Controls.Hybrid
}
}
+ ///
+ /// Returns the number of item rows per page.
+ ///
+ public int ItemRowsPerPage
+ {
+ get
+ {
+ return this.MaximumRow - this.LayoutRows;
+ }
+ }
+
public int PageCount
{
get
{
- if (this.ButtonsForm.Count == 0)
+ if (DataSource.RowCount == 0)
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 != "")
//{
// bf = bf.FilterDuplicate(this.SearchQuery);
//}
- if (bf.Rows == 0)
+ if (max == 0)
return 1;
- return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows)));
+ return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
}
}
diff --git a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs
index d97f920..55ed12e 100644
--- a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs
+++ b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs
@@ -7,9 +7,11 @@ using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
+using Telegram.Bot.Types.InlineQueryResults;
using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
+using TelegramBotBase.Datasources;
using TelegramBotBase.Enums;
using TelegramBotBase.Exceptions;
using TelegramBotBase.Form;
@@ -30,7 +32,23 @@ namespace TelegramBotBase.Controls.Hybrid
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);
+ }
+ }
+
+ ///
+ /// Data source of the items.
+ ///
+ public ButtonFormDataSource DataSource { get; set; }
public int? MessageId { get; set; }
@@ -62,6 +80,11 @@ namespace TelegramBotBase.Controls.Hybrid
///
public bool EnablePaging { get; set; } = false;
+ ///
+ /// Shows un-/check all tags options
+ ///
+ public bool EnableCheckAllTools { get; set; } = false;
+
///
/// Enabled a search function.
///
@@ -87,15 +110,24 @@ namespace TelegramBotBase.Controls.Hybrid
public String BackLabel = Localizations.Default.Language["ButtonGrid_Back"];
+ public String CheckAllLabel = Localizations.Default.Language["ButtonGrid_CheckAll"];
+
+ public String UncheckAllLabel = Localizations.Default.Language["ButtonGrid_UncheckAll"];
+
///
/// Layout of the buttons which should be displayed always on top.
///
- public List HeadLayoutButtonRow { get; set; }
+ public ButtonRow HeadLayoutButtonRow { get; set; }
///
/// Layout of columns which should be displayed below the header
///
- public List SubHeadLayoutButtonRow { get; set; }
+ public ButtonRow SubHeadLayoutButtonRow { get; set; }
+
+ ///
+ /// Layout of columns which should be displayed below the header
+ ///
+ private ButtonRow TagsSubHeadLayoutButtonRow { get; set; }
///
/// List of Tags which will be allowed to filter by.
@@ -134,7 +166,7 @@ namespace TelegramBotBase.Controls.Hybrid
public TaggedButtonGrid()
{
- this.ButtonsForm = new ButtonForm();
+ this.DataSource = new ButtonFormDataSource();
this.SelectedViewIndex = 0;
}
@@ -147,7 +179,7 @@ namespace TelegramBotBase.Controls.Hybrid
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 == "")
return;
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
+ var matches = new List();
+ ButtonRow match = null;
+ 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)
{
case 0:
- if (button != null)
- {
- await OnButtonClicked(new ButtonClickedEventArgs(button, index));
+ //Remove button click message
+ if (this.DeleteReplyMessage)
+ await Device.DeleteMessage(result.MessageId);
- //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;
-
return;
}
@@ -287,17 +352,25 @@ namespace TelegramBotBase.Controls.Hybrid
break;
case 1:
+ //Remove button click message
+ if (this.DeleteReplyMessage)
+ await Device.DeleteMessage(result.MessageId);
+
if (result.MessageText == this.BackLabel)
{
- //Remove button click message
- if (this.DeletePreviousMessage)
- await Device.DeleteMessage(result.MessageId);
-
this.SelectedViewIndex = 0;
this.Updated();
result.Handled = true;
return;
}
+ else if (result.MessageText == this.CheckAllLabel)
+ {
+ this.CheckAllTags();
+ }
+ else if (result.MessageText == this.UncheckAllLabel)
+ {
+ this.UncheckAllTags();
+ }
var i = result.MessageText.LastIndexOf(" ");
if (i == -1)
@@ -340,15 +413,48 @@ namespace TelegramBotBase.Controls.Hybrid
await result.ConfirmAction(this.ConfirmationText ?? "");
- var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
- ?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
+ ButtonRow match = null;
+ int index = -1;
- var index = ButtonsForm.FindRowByButton(button);
-
- if (button != null)
+ if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
{
- 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;
return;
@@ -386,6 +492,18 @@ namespace TelegramBotBase.Controls.Hybrid
this.SelectedViewIndex = 0;
this.Updated();
+ break;
+
+ case "$checkall$":
+
+ this.CheckAllTags();
+
+ break;
+
+ case "$uncheckall$":
+
+ this.UncheckAllTags();
+
break;
}
@@ -400,28 +518,28 @@ namespace TelegramBotBase.Controls.Hybrid
{
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;
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;
@@ -468,16 +586,16 @@ namespace TelegramBotBase.Controls.Hybrid
{
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 != "")
- {
- form = form.FilterDuplicate(this.SearchQuery, true);
- }
- else
- {
- form = form.Duplicate();
- }
+ //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
+ //{
+ // form = form.FilterDuplicate(this.SearchQuery, true);
+ //}
+ //else
+ //{
+ // form = form.Duplicate();
+ //}
if (this.Tags != null && this.SelectedTags != null)
{
@@ -486,23 +604,23 @@ namespace TelegramBotBase.Controls.Hybrid
if (this.EnablePaging)
{
- form = GeneratePagingView(form);
+ IntegratePagingView(form);
}
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.IsNavigationBarVisible)
{
- form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
+ form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
}
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
- if (this.ButtonsForm.Count == 0)
+ if (dataForm.Rows == 0)
{
- bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
+ dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
}
if (this.IsNavigationBarVisible)
{
//🔍
- List lst = new List();
- lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
- lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
+ ButtonRow row = new ButtonRow();
+ row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
+ 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)
{
- 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)
{
- 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
@@ -620,6 +723,12 @@ namespace TelegramBotBase.Controls.Hybrid
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)
{
@@ -748,7 +857,7 @@ namespace TelegramBotBase.Controls.Hybrid
{
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)
layoutRows++;
+ if (EnableCheckAllTools && this.SelectedViewIndex == 1)
+ {
+ layoutRows++;
+ }
+
return layoutRows;
}
}
+ ///
+ /// Returns the number of item rows per page.
+ ///
+ public int ItemRowsPerPage
+ {
+ get
+ {
+ return this.MaximumRow - this.LayoutRows;
+ }
+ }
+
public int PageCount
{
get
{
- if (this.ButtonsForm.Count == 0)
+ if (DataSource.RowCount == 0)
return 1;
- var bf = this.ButtonsForm;
+ //var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
- if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
- {
- bf = bf.FilterDuplicate(this.SearchQuery);
- }
+ var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
- if (bf.Rows == 0)
+ //if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
+ //{
+ // bf = bf.FilterDuplicate(this.SearchQuery);
+ //}
+
+ if (max == 0)
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;
}
+ }
+
///
/// Checks all tags for filtering.
diff --git a/TelegramBotBase/Datasources/ButtonFormDataSource.cs b/TelegramBotBase/Datasources/ButtonFormDataSource.cs
new file mode 100644
index 0000000..e8fbfd4
--- /dev/null
+++ b/TelegramBotBase/Datasources/ButtonFormDataSource.cs
@@ -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
+ {
+ 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;
+ }
+
+
+ ///
+ /// Returns the amount of rows exisiting.
+ ///
+ ///
+ public virtual int Count => ButtonForm.Count;
+
+
+ ///
+ /// Returns the amount of rows.
+ ///
+ public virtual int RowCount => ButtonForm.Rows;
+
+ ///
+ /// Returns the maximum amount of columns.
+ ///
+ public virtual int ColumnCount => ButtonForm.Cols;
+
+ ///
+ /// Returns the row with the specific index.
+ ///
+ ///
+ ///
+ public virtual ButtonRow ItemAt(int index)
+ {
+ return ButtonForm[index];
+ }
+
+ public virtual List ItemRange(int start, int count)
+ {
+ return ButtonForm.GetRange(start, count);
+ }
+
+ public virtual List 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 FindRow(String text, bool useText = true)
+ {
+ return ButtonForm.FindRow(text, useText);
+ }
+
+ ///
+ /// Returns the maximum items of this data source.
+ ///
+ ///
+ ///
+ 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;
+ }
+
+ }
+}
diff --git a/TelegramBotBase/Datasources/StaticDataSource.cs b/TelegramBotBase/Datasources/StaticDataSource.cs
new file mode 100644
index 0000000..19ff96c
--- /dev/null
+++ b/TelegramBotBase/Datasources/StaticDataSource.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TelegramBotBase.Datasources
+{
+ public class StaticDataSource : Interfaces.IDataSource
+ {
+ List Data { get; set; }
+
+ public StaticDataSource()
+ {
+
+ }
+
+ public StaticDataSource(List data)
+ {
+ this.Data = data;
+ }
+
+
+ public int Count
+ {
+ get
+ {
+ return Data.Count;
+ }
+ }
+
+ public T ItemAt(int index)
+ {
+ return Data[index];
+ }
+
+ public List ItemRange(int start, int count)
+ {
+ return Data.Skip(start).Take(count).ToList();
+ }
+
+ public List AllItems()
+ {
+ return Data;
+ }
+ }
+}
diff --git a/TelegramBotBase/Form/ButtonForm.cs b/TelegramBotBase/Form/ButtonForm.cs
index be32f49..c477b37 100644
--- a/TelegramBotBase/Form/ButtonForm.cs
+++ b/TelegramBotBase/Form/ButtonForm.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Base;
+using TelegramBotBase.Controls.Hybrid;
namespace TelegramBotBase.Form
{
@@ -13,7 +14,7 @@ namespace TelegramBotBase.Form
///
public class ButtonForm
{
- List> Buttons = new List>();
+ List Buttons = new List();
public IReplyMarkup Markup { get; set; }
@@ -43,7 +44,7 @@ namespace TelegramBotBase.Form
}
- public List this[int row]
+ public ButtonRow this[int row]
{
get
{
@@ -66,9 +67,14 @@ namespace TelegramBotBase.Form
Buttons.Add(new List() { new ButtonBase(Text, Value, Url) });
}
- public void AddButtonRow(IEnumerable 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)
@@ -76,16 +82,26 @@ namespace TelegramBotBase.Form
AddButtonRow(row.ToList());
}
+ public void AddButtonRows(IEnumerable rows)
+ {
+ Buttons.AddRange(rows);
+ }
+
public void InsertButtonRow(int index, IEnumerable row)
{
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(IEnumerable items, int itemsPerRow = 2)
{
T[][] splitted = default(T[][]);
@@ -132,34 +148,62 @@ namespace TelegramBotBase.Form
}
}
+ ///
+ /// Returns a range of rows from the buttons.
+ ///
+ ///
+ ///
+ ///
+ public List GetRange(int start, int count)
+ {
+ return Buttons.Skip(start).Take(count).ToList();
+ }
+
+
public List ToList()
{
- return this.Buttons.DefaultIfEmpty(new List()).Aggregate((a, b) => a.Union(b).ToList());
+ return this.Buttons.DefaultIfEmpty(new List()).Select(a => a.ToList()).Aggregate((a, b) => a.Union(b).ToList());
}
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;
}
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;
}
+ public List ToArray()
+ {
+ return Buttons;
+ }
+
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)
return -1;
return this.Buttons.IndexOf(row);
}
+ public Tuple 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(r, i);
+ }
+
+
///
/// Returns the first Button with the given value.
///
@@ -204,7 +248,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons)
{
- var lst = new List();
+ var lst = new ButtonRow();
foreach (var b2 in b)
{
lst.Add(b2);
@@ -229,7 +273,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons)
{
- var lst = new List();
+ var lst = new ButtonRow();
foreach (var b2 in b)
{
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.
if (ByRow)
{
- lst.AddRange(b);
+ lst = b;
break;
}
else
@@ -268,7 +312,7 @@ namespace TelegramBotBase.Form
foreach (var b in Buttons)
{
- var lst = new List();
+ var lst = new ButtonRow();
foreach (var b2 in b)
{
if (!(b2 is TagButtonBase tb))
@@ -280,7 +324,7 @@ namespace TelegramBotBase.Form
//Copy full row, when at least one match has found.
if (ByRow)
{
- lst.AddRange(b);
+ lst = b;
break;
}
else
diff --git a/TelegramBotBase/Interfaces/IDataSource.cs b/TelegramBotBase/Interfaces/IDataSource.cs
new file mode 100644
index 0000000..d3662e5
--- /dev/null
+++ b/TelegramBotBase/Interfaces/IDataSource.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TelegramBotBase.Controls.Hybrid;
+
+namespace TelegramBotBase.Interfaces
+{
+ public interface IDataSource
+ {
+
+ ///
+ /// Returns the amount of items within this source.
+ ///
+ ///
+ int Count { get; }
+
+
+ ///
+ /// Returns the item at the specific index.
+ ///
+ ///
+ ///
+ T ItemAt(int index);
+
+
+ ///
+ /// Get all items from this source within this range.
+ ///
+ ///
+ ///
+ ///
+ List ItemRange(int start, int count);
+
+
+ ///
+ /// Gets a list of all items of this datasource.
+ ///
+ ///
+ List AllItems();
+
+
+ }
+}
diff --git a/TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs b/TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs
index 1060754..c737d10 100644
--- a/TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs
+++ b/TelegramBotBaseTest/Tests/Controls/ButtonGridTagForm.cs
@@ -32,6 +32,7 @@ namespace TelegramBotBaseTest.Tests.Controls
m_Buttons.EnablePaging = true;
m_Buttons.HeadLayoutButtonRow = new List() { new ButtonBase("Back", "back") };
+
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
@@ -45,7 +46,9 @@ namespace TelegramBotBaseTest.Tests.Controls
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.ButtonsForm = bf;
+ m_Buttons.EnableCheckAllTools = true;
+
+ m_Buttons.DataSource = new TelegramBotBase.Datasources.ButtonFormDataSource(bf);
m_Buttons.ButtonClicked += Bg_ButtonClicked;
@@ -57,11 +60,13 @@ namespace TelegramBotBaseTest.Tests.Controls
if (e.Button == null)
return;
- if (e.Button.Value == "back")
+ switch (e.Button.Value)
{
- var start = new Menu();
- await this.NavigateTo(start);
- return;
+
+ case "back":
+ var start = new Menu();
+ await this.NavigateTo(start);
+ return;
}
diff --git a/TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs b/TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs
new file mode 100644
index 0000000..3187968
--- /dev/null
+++ b/TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs
@@ -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 Countries = new List() { "Country 1", "Country 2", "Country 3" };
+
+ public CustomDataSource()
+ {
+ loadData();
+ }
+
+ ///
+ /// 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.
+ ///
+ private void loadData()
+ {
+ //Exists data source? Read it
+ if (File.Exists(AppContext.BaseDirectory + "countries.json"))
+ {
+ try
+ {
+ var List = Newtonsoft.Json.JsonConvert.DeserializeObject>(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 ItemRange(int start, int count)
+ {
+ var items = Countries.Skip(start).Take(count);
+
+ List lst = new List();
+ foreach (var c in items)
+ {
+ lst.Add(Render(c));
+ }
+
+ return lst;
+ }
+
+ public override List AllItems()
+ {
+ List lst = new List();
+ foreach (var c in Countries)
+ {
+ lst.Add(Render(c));
+ }
+ return lst;
+ }
+
+ public override ButtonForm PickItems(int start, int count, string filter = null)
+ {
+ List 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 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;
+ }
+ }
+
+ }
+}
diff --git a/TelegramBotBaseTest/Tests/Datasources/List.cs b/TelegramBotBaseTest/Tests/Datasources/List.cs
new file mode 100644
index 0000000..b2ec372
--- /dev/null
+++ b/TelegramBotBaseTest/Tests/Datasources/List.cs
@@ -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)
+ {
+
+ }
+
+
+ }
+}
diff --git a/TelegramBotBaseTest/Tests/Menu.cs b/TelegramBotBaseTest/Tests/Menu.cs
index e4de4f0..8f96053 100644
--- a/TelegramBotBaseTest/Tests/Menu.cs
+++ b/TelegramBotBaseTest/Tests/Menu.cs
@@ -190,6 +190,14 @@ namespace TelegramBotBaseTest.Tests
await NavigateTo(nc);
+ break;
+
+ case "dynamicbuttongrid":
+
+ var dg = new Datasources.List();
+
+ await NavigateTo(dg);
+
break;
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("#18 Dynamic ButtonGrid (DataSources)", new CallbackData("a", "dynamicbuttongrid").Serialize()));
+
await this.Device.Send("Choose your test:", btn);
}