diff --git a/README.md b/README.md
index ea0cee1..a81b53a 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,8 @@ Thanks !
* [CheckedButtonList](#checked-button-list)
+ * [MultiToggleButton](#multi-toggle-button)
+
- [Groups](#groups)
* [SplitterForm](#splitter-form)
@@ -814,6 +816,8 @@ await this.NavigateTo(cd);
### Checked Button List
+### Multi Toggle Button
+
## Groups
diff --git a/TelegramBotBase/Controls/Inline/MultiToggleButton.cs b/TelegramBotBase/Controls/Inline/MultiToggleButton.cs
new file mode 100644
index 0000000..d5f44f3
--- /dev/null
+++ b/TelegramBotBase/Controls/Inline/MultiToggleButton.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TelegramBotBase.Base;
+using TelegramBotBase.Form;
+
+namespace TelegramBotBase.Controls.Inline
+{
+ public class MultiToggleButton : ControlBase
+ {
+
+ //public String UncheckedIcon { get; set; } = Localizations.Default.Language["ToggleButton_OffIcon"];
+
+ public String CheckedIcon { get; set; } = "✅";
+
+ public String ChangedString { get; set; } = Localizations.Default.Language["ToggleButton_Changed"];
+
+ public String Title { get; set; } = Localizations.Default.Language["ToggleButton_Title"];
+
+ public int? MessageId { get; set; }
+
+ private bool RenderNecessary = true;
+
+ private static readonly object __evToggled = new object();
+
+ private readonly EventHandlerList Events = new EventHandlerList();
+
+ public List Options { get; set; }
+
+
+ public MultiToggleButton()
+ {
+ Options = new List();
+ }
+
+ public event EventHandler Toggled
+ {
+ add
+ {
+ this.Events.AddHandler(__evToggled, value);
+ }
+ remove
+ {
+ this.Events.RemoveHandler(__evToggled, value);
+ }
+ }
+
+ public void OnToggled(EventArgs e)
+ {
+ (this.Events[__evToggled] as EventHandler)?.Invoke(this, e);
+ }
+
+ public override async Task Action(MessageResult result, String value = null)
+ {
+ if (result.Handled)
+ return;
+
+ await result.ConfirmAction(this.ChangedString);
+
+ switch (value ?? "unknown")
+ {
+ default:
+
+ var s = value.Split('$');
+
+ if (s[0] == "check" && s.Length > 1)
+ {
+ int index = 0;
+ if (!int.TryParse(s[1], out index))
+ {
+ return;
+ }
+
+ if(SelectedOption== null || SelectedOption != this.Options[index])
+ {
+ this.SelectedOption = this.Options[index];
+ OnToggled(new EventArgs());
+ }
+ else
+ {
+ this.SelectedOption = null;
+ OnToggled(new EventArgs());
+ }
+
+ RenderNecessary = true;
+
+ return;
+ }
+
+
+ RenderNecessary = false;
+
+ break;
+
+ }
+
+ result.Handled = true;
+
+ }
+
+ public override async Task Render(MessageResult result)
+ {
+ if (!RenderNecessary)
+ return;
+
+ var bf = new ButtonForm(this);
+
+ var lst = new List();
+ foreach (var o in this.Options)
+ {
+ var index = this.Options.IndexOf(o);
+ if (o == this.SelectedOption)
+ {
+ lst.Add(new ButtonBase(CheckedIcon + " " + o.Text, "check$" + index));
+ continue;
+ }
+
+ lst.Add(new ButtonBase(o.Text, "check$" + index));
+ }
+
+ bf.AddButtonRow(lst);
+
+ if (this.MessageId != null)
+ {
+ var m = await this.Device.Edit(this.MessageId.Value, this.Title, bf);
+ }
+ else
+ {
+ var m = await this.Device.Send(this.Title, bf, disableNotification: true);
+ if (m != null)
+ {
+ this.MessageId = m.MessageId;
+ }
+ }
+
+ this.RenderNecessary = false;
+
+
+ }
+
+ public ButtonBase SelectedOption
+ {
+ get; set;
+ }
+
+ }
+}
diff --git a/TelegramBotBaseTest/Tests/Controls/MultiToggleButtons.cs b/TelegramBotBaseTest/Tests/Controls/MultiToggleButtons.cs
new file mode 100644
index 0000000..54fddca
--- /dev/null
+++ b/TelegramBotBaseTest/Tests/Controls/MultiToggleButtons.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TelegramBotBase.Args;
+using TelegramBotBase.Controls;
+using TelegramBotBase.Controls.Inline;
+using TelegramBotBase.Form;
+
+namespace TelegramBotBaseTest.Tests.Controls
+{
+ public class MultiToggleButtons : AutoCleanForm
+ {
+ public MultiToggleButtons()
+ {
+ this.DeleteMode = TelegramBotBase.Enums.eDeleteMode.OnLeavingForm;
+
+ this.Init += ToggleButtons_Init;
+ }
+
+ private async Task ToggleButtons_Init(object sender, InitEventArgs e)
+ {
+
+ var mtb = new MultiToggleButton();
+
+ mtb.Options = new List() { new ButtonBase("Option 1", "1"), new ButtonBase("Option 2", "2"), new ButtonBase("Option 3", "3") };
+ mtb.SelectedOption = mtb.Options.FirstOrDefault();
+ mtb.Toggled += Tb_Toggled;
+ this.AddControl(mtb);
+
+ mtb = new MultiToggleButton();
+
+ mtb.Options = new List() { new ButtonBase("Option 4", "4"), new ButtonBase("Option 5", "5"), new ButtonBase("Option 6", "6") };
+ mtb.SelectedOption = mtb.Options.FirstOrDefault();
+ mtb.Toggled += Tb_Toggled;
+ this.AddControl(mtb);
+ }
+
+ private void Tb_Toggled(object sender, EventArgs e)
+ {
+ var tb = sender as MultiToggleButton;
+ Console.WriteLine(tb.ID.ToString() + " was pressed, and toggled to " + tb.SelectedOption.Value);
+ }
+ }
+}
diff --git a/TelegramBotBaseTest/Tests/Menu.cs b/TelegramBotBaseTest/Tests/Menu.cs
index d72d04f..57cf9fb 100644
--- a/TelegramBotBaseTest/Tests/Menu.cs
+++ b/TelegramBotBaseTest/Tests/Menu.cs
@@ -140,6 +140,17 @@ namespace TelegramBotBaseTest.Tests
await this.NavigateTo(tb);
break;
+
+ case "multitogglebuttons":
+
+ message.Handled = true;
+
+ var mtb = new Controls.MultiToggleButtons();
+
+ await this.NavigateTo(mtb);
+
+ break;
+
case "buttongrid":
message.Handled = true;
@@ -217,6 +228,8 @@ namespace TelegramBotBaseTest.Tests
btn.AddButtonRow(new ButtonBase("#11 ToggleButtons", new CallbackData("a", "togglebuttons").Serialize()));
+ btn.AddButtonRow(new ButtonBase("#11.2 MultiToggleButtons", new CallbackData("a", "multitogglebuttons").Serialize()));
+
btn.AddButtonRow(new ButtonBase("#12 ButtonGrid", new CallbackData("a", "buttongrid").Serialize()));
btn.AddButtonRow(new ButtonBase("#13 ButtonGrid Paging & Filter", new CallbackData("a", "buttongridfilter").Serialize()));
diff --git a/images/multitogglebutton.gif b/images/multitogglebutton.gif
new file mode 100644
index 0000000..b399eae
Binary files /dev/null and b/images/multitogglebutton.gif differ