How to create an inline keyboard with multiple rows in TelegramBotAPI? - c#

How can I create an inline keyboard with several buttons, one per row?
like:
inlineBtn1
inlineBtn2
inlineBtn3
...
not:
inlineBtn1 inlineBtn2 inlineBtn3 ...

I Solved it
await bot.SendTextMessageAsync(e.Message.Chat.Id, "test", replyMarkup: new InlineKeyboardMarkup(
new InlineKeyboardButton[][]
{
new [] { new InlineKeyboardButton() { Text = "btn 1",CallbackData="Some data1" } }, // buttons in row 1
new [] { new InlineKeyboardButton() { Text = "btn 2", CallbackData = "Some data2" } }, // buttons in row 2
new [] { new InlineKeyboardButton() {Text = "btn 3", CallbackData = "Some data3" } }// buttons in row 3
}));
We must use exactly one of the optional fields.
So you have to pass either url, callback_data or switch_inline_query The button would be useless if you don't pass any of those fields.

To send a message to a chat with an inline keyboard use the replyMarkup parameter of TelegramBot.SendMessage or TelegramBot.SendMessageAsync method. It can be either ReplyKeyboardMarkup or InlineKeyboardMarkup. A constructor of InlineKeyboardMarkup accepts an array of button rows (each of them, in turn, comprises an array of buttons in the given row). To create an inline keyboard with several buttons one per row pass an array with several rows with one element each:
TelegramBot bot = ...;
Chat chat = ...;
await bot.SendMessageAsync(chat.Id, "A message. Use the keyboard below.",
replyMarkup: new InlineKeyboardMarkup(
new InlineKeyboardButton[][]
{
new [] { new InlineKeyboardButton("inlineBtn1") }, // buttons in row 1
new [] { new InlineKeyboardButton("inlineBtn2") }, // buttons in row 2
new [] { new InlineKeyboardButton("inlineBtn3") } // buttons in row 3
}));
The message should look like this:

Related

LiveChart.WinForm: Column Series' X-axis not displaying as required

I am reading data from Firebase Firestore and displaying it using a Cartesian Chart. Here is the function that takes some data parameters and then draws the graph:
public void DrawGraph(double allowed, double denied, double pending)
{
cartesianChart1.Series = new SeriesCollection
{
new ColumnSeries
{
Title = DateTime.Today.ToString("dd/MM/yyy"),
Values = new ChartValues<double> { allowed, denied, pending },
}
};
cartesianChart1.AxisX.Add(new Axis
{
Title = "Requests",
Labels = new[] { "Allowed", "Denied", "Pending"}
});
}
Here is the actual output:
The problem here is that the labels "Allowed", "Denied", and "Pending" are not appearing as they should, e.g.
In this case, the data isn't loaded and the graph code is written inside the constructor of the parent WinForm. And when the data is loaded it shows the same results as shown in the first image.

Adaptive card action button text & UI trimmed inside the MS Team Channel

I'm having an issue where buttons and actions in ms teams adaptive cards won’t wrap text inside the action button. The button UI is completely broken even if we are applied " full: width" in MS Team. I know the "Wrap: true || false" we can add inside the adaptive card body or title of the textblock, Is there any other way to handle this type of scenario in the action button title in MS Team channel.
The following code we are using for the adaptive card implementation.
public static Attachment ChoiceMenu(string channelType, string text, List buttons, string subCategory = null)
{
var menuCard = new AdaptiveCard("1.2");
if(!string.IsNullOrEmpty(subCategory))
{
menuCard.Body.Add(new AdaptiveTextBlock()
{
Text = subCategory,
Size = AdaptiveTextSize.Large,
Wrap = true,
});
}
menuCard.Body.Add(new AdaptiveTextBlock()
{
Text = text,
Wrap = true,
});
foreach (var button in buttons)
{
var columns = new AdaptiveColumnSet();
menuCard.Body.Add(columns);
var userCategory = new AdaptiveColumn();
columns.Columns.Add(userCategory);
var actionType = new AdaptiveActionSet();
userCategory.Items.Add(actionType);
var submitAction = new AdaptiveSubmitAction()
{
Title = button,
Id = button
};
if (channelType == Channels.Msteams)
{
submitAction.Data = new AdaptiveCardDataObjectForTeams()
{
MsTeams = new MsTeamsObject()
{
Type = ActionTypes.MessageBack,
DisplayText = button,
Text = button
}
};
}
else
{
submitAction.Data = button;
}
actionType.Actions.Add(submitAction);
}
return new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = menuCard
};
}
Platform
Web ( MsTeams Web http://teams.microsoft.com ) Microsoft Teams
Version 1.4.00.32771 (64-bit). It was last updated on 12/15/2021.
Adaptive Card Version
1.2
As per the Format cards in Microsoft Teams docs,
Cards support formatting in the text property only, not in the title
or subtitle properties.
Note: The Action Button text is in the title property, This is the reason we cannot do any formatting for it. So there is no way to wrap text in the Action Button.
Alternate Solution:
We have changed the MS Team title of the button using the substring concatenation, hereafter the particular character will display "...", So this way we can alternatively fix this issue.
submitAction.Title = button.Length > 50 ? string.Concat(button.Substring(0, 50), "...") : button;
Output:
Reference:
Github discussion
Apart from using full width property in Adaptive card, there doesn't seem to be any way to increase the size of actionable buttons in adaptive card in order to fit the text/title properly.
"msteams": {
"width": "Full"
}

How can I disable the AdaptiveSubmitAction button once activated?

I'm using "microsoft bot builder" library to build a bot in c#.
I have a card that contains an AdaptiveSubmitAction button which will present a new card on click.
I want to disable the submit button once its activated.. how would that be possible?
This is a part of my code:
////// Submit and Finish button ///////
card.Body.Add(new AdaptiveColumnSet()
{
Columns = new List<AdaptiveColumn>()
{
new AdaptiveColumn()
{
Width = "auto",
Items = new List<AdaptiveElement>()
{
new AdaptiveActionSet()
{
Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Title = "Submit",
Id = "Submit",
//from the data you can trigger actions
//e.g.:
Data = new {isDone = false, deleteCrit = false}
},
}
}
}
},
new AdaptiveColumn()
{
Width = "auto",
Items = new List<AdaptiveElement>()
{
new AdaptiveActionSet()
{
Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Title = "End",
Id = "Finished",
Data = new {isDone = true, deleteCrit = false}
}
}
}
}
},
}
});
Any help is appreciated!
What you're asking for is impossible because neither Adaptive Cards nor Teams has a concept of a double click when it comes to submit actions. If you were using Web Chat then you might be able to build a custom solution but Teams does not allow for that kind of customizability. If you need a submit action to function in multiple possible ways then I recommend using two different submit actions instead.
You can send feedback to Teams through the Teams app directly or you can submit feature requests in the Teams docs repo or the Adaptive Cards repo.
Yes this should be possible, I believe you can update the Adaptive card view after the first click with only change in view being that the button will be in disabled view. Not only this you can make any change in the card and it will retroactively refresh the view of that card ID. For usage, see context.updateactivity and it's implementation details.

Add click gesture recognizer on stack child (item in scroll)

I've got a stack layout inside a gridview, that I use as a sort of list.
The "items" in the list have to be click/tap -able, but I can't find a way to make the child area clickable while also giving a value to the event to know what item the user clicked.
Right now I create 20 items in a for loop. The "i" is an integer used for counting.
I put an BoxView over the original boxview and label of the item, which is transparent and gets the gesturerecognizer.
var clickableBoxv = new BoxView
{
BackgroundColor = Color.Transparent,
Margin = new Thickness(0, 5, 0, 5)
};
clickableBoxv.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(() => Item_Clicked(i)),
});
private void Item_Clicked(int num)
{
DisplayAlert("Alert", num.ToString(), "OK");
}
But when I click the item, it shows an alert with only the last added number. (which didn't surprise me). But how can I get the alert to show me the specific item number?
While I haven't tested your exact code I have reproduced the same behaviour with some Actions inside a for loop.
Option 1 - Track the boxes.
It might not be the most ideal of solutions but one option would be to keep track of your boxes and use their index in the collection to represent the number.
// 1. A place to store the boxes.
IList<BoxView> boxes = new List<BoxView>();
var clickableBoxv = new BoxView
{
BackgroundColor = Color.Transparent,
Margin = new Thickness(0, 5, 0, 5)
};
// 2. Keep track of your clickable boxes.
boxes.Add(clickableBoxv);
clickableBoxv.GestureRecognizers.Add(new TapGestureRecognizer
{
// 3. Pass in the box rather than the int.
Command = new Command(() => Item_Clicked(clickableBoxv)),
});
private void Item_Clicked(BoxView box)
{
// 4. Use the index as the number.
DisplayAlert("Alert", boxes.IndexOf(box).ToString(), "OK");
}
Option 2 - sub class BoxView
// 1. Sub class
public class MyBoxView : BoxView
{
public int Index { get; set; }
}
// 2. Use new sub class
var clickableBoxv = new MyBoxView
{
BackgroundColor = Color.Transparent,
Margin = new Thickness(0, 5, 0, 5),
Index = i,
};
clickableBoxv.GestureRecognizers.Add(new TapGestureRecognizer
{
// 3. Pass in the box rather than the int.
Command = new Command(() => Item_Clicked(clickableBoxv)),
});
private void Item_Clicked(MyBoxView box)
{
// 4. Use the index as the number.
DisplayAlert("Alert", box.Index.ToString(), "OK");
}

Why doesn't my ListView show Details view properly?

So, I've got a list view, as indicated by the question title. I've got two columns set up: Name and Date Modified. These were added in the designer, here's the code emitted by the designer for reference:
// lstFiles
this.lstFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.clmName,
this.clmDate});
// ...
// clmName
this.clmName.Text = "Name";
this.clmName.Width = 105;
// clmDate
this.clmDate.Text = "Modified";
this.clmDate.Width = 128;
In the designer, this looks beautiful.
The list items themselves are a tiny subclass of ListViewItem that simply extracts some metadata from a file (in this case, the date modified), and adds a sub-item to itself:
class GalleryItem : ListViewItem {
public string File;
public DateTime DateModified;
public GalleryItem(string file) : base(Path.GetFileNameWithoutExtension(file)) {
this.ImageKey = Path.GetExtension(file);
File = file;
DateModified = System.IO.File.GetLastWriteTime(file);
this.SubItems.Add(DateModified.ToString());
}
}
To add items to the list, I simply do this:
lstFiles.BeginUpdate();
lstFiles.Clear();
foreach (String f in files) {
ListViewItem lvi = new GalleryItem(f);
lvi.Group = lstFiles.Groups["grpFiles"]; //this varries
//omitted: check/add icon to list
lstFiles.Items.Add(lvi);
}
lstFiles.EndUpdate();
So, this all works great for Large Icon view, etc:
However, it breaks down on Details view:
There are items in the list (there's a scroll bar). If you click roughly in the column under the red arrow (added in paint), you'll select an item (the upper-right area is an image preview), but you won't see anything selected.
In summary, what am I doing wrong?
I just whipped up a sample to test this:
using System;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var G1 = new ListViewGroup("Group 1");
var G2 = new ListViewGroup("Group 2");
Application.Run(new Form {
Controls = {
new ListView {
Dock = DockStyle.Fill,
Groups = { G1, G2 },
View = View.Details,
//Columns = { "First", "Second" },
Items = {
new ListViewItem { Text = "One", Group = G1, SubItems = { "1" } },
new ListViewItem { Text = "Two", Group = G2, SubItems = { "2" } },
new ListViewItem { Text = "Three", Group = G2, SubItems = { "3" } },
},
},
},
});
}
}
You will notice that it duplicates the problem. If you uncomment the line that creates the columns it works. This suggests that your columns don't exist.
And while typing this the answer popped into my head:
You are calling ListView.Clear instead of ListView.Items.Clear so you are removing the columns in code.
My understanding is that you are not able to use Groups in Details view. I can't test this right now, so I am going off straight memory. However, try populating your list without the Groups and see what happens. I strongly suspect it is the Group part that is causing the problem.
I had exactly the same problem identified by Tergiver, but there is one more gotcha - when you add the columns, the ListView must be in View.Details mode.

Categories