Reputation: 51
I am using ChoicePrompt in WaterfallStep for displaying choices. The issue is if the choice list is greater than 10, I am not getting buttons, That's displaying as text. Please help me on how to fix this error.
var waterfallSteps = new WaterfallStep[]
{
InitializeStateStepAsync,
PromptShowChoiceStepAsync,
DisplaySuccessStepAsync,
};
AddDialog(new WaterfallDialog("waterfallDialog", waterfallSteps));
AddDialog(new ChoicePrompt("ShowChoicePrompt", ValidateShowChoice));
private async Task<DialogTurnResult> ValidateShowChoice(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync("ShowChoicePrompt", new PromptOptions
{
Prompt = MessageFactory.Text("Please select from choices"),
RetryPrompt = MessageFactory.Text("Sorry, Please the valid choice"),
Choices = ChoiceFactory.ToChoices(choicesList),
}, cancellationToken);
}
}
If choicesList count is greater than 10, I am getting the buttons like this. Which is not an issue in Bot framework V3.
Please select from choices
1. Choice-1
2. Choice-2
3. Choice-3
4. Choice-4
5. Choice-5
6. Choice-6
7. Choice-7
8. Choice-8
9. Choice-9
10. Choice-10
11. Choice-11
12. Choice-12
13. Choice-13
Please help me how to resolve this error.
Upvotes: 1
Views: 2777
Reputation: 12264
Choice prompts in v3 used hero cards by default. You can force your prompts to use hero cards with the new HeroCard
option in the ListStyle
enum. The list style can be applied directly to the prompt when you add it to your dialog set:
AddDialog(new ChoicePrompt("ShowChoicePrompt", ValidateShowChoice) { Style = ListStyle.HeroCard });
You also now have the ability to specify a list style in the prompt options:
return await stepContext.PromptAsync("ShowChoicePrompt", new PromptOptions
{
Prompt = MessageFactory.Text("Please select from choices"),
RetryPrompt = MessageFactory.Text("Sorry, Please the valid choice"),
Choices = ChoiceFactory.ToChoices(choicesList),
Style = ListStyle.HeroCard,
}, cancellationToken);
While it's true that it's bad practice to include too many buttons in a message and most channels enforce this convention by not allowing a lot of buttons on a card, the connectors for Facebook and Skype will automatically generate multiple cards if you try to put too many buttons on one card.
In Facebook Messenger it will look like this:
In Skype it will look like this:
Upvotes: 2
Reputation: 14589
These display choices are made due to limitations / guidelines on the channels used.
If you have a look to Facebook Messenger developer's page about Quick replies
here, it states:
Quick replies provide a way to present a set of up to 11 buttons in-conversation that contain a title and optional image, and appear prominently above the composer. You can also use quick replies to request a person's location, email address, and phone number.
As a consequence, in the code of the BotBuilder available on Github, you will have a method to Determine if a number of Suggested Actions are supported by a Channel
here:
/// <summary>
/// Determine if a number of Suggested Actions are supported by a Channel.
/// </summary>
/// <param name="channelId">The Channel to check the if Suggested Actions are supported in.</param>
/// <param name="buttonCnt">(Optional) The number of Suggested Actions to check for the Channel.</param>
/// <returns>True if the Channel supports the buttonCnt total Suggested Actions, False if the Channel does not support that number of Suggested Actions.</returns>
public static bool SupportsSuggestedActions(string channelId, int buttonCnt = 100)
{
switch (channelId)
{
// https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies
case Connector.Channels.Facebook:
case Connector.Channels.Skype:
return buttonCnt <= 10;
// ...
}
}
Then, in the ChoiceFactory
that you used, the display is selected (see code here):
public static IMessageActivity ForChannel(string channelId, IList<Choice> list, string text = null, string speak = null, ChoiceFactoryOptions options = null)
{
channelId = channelId ?? string.Empty;
list = list ?? new List<Choice>();
// Find maximum title length
var maxTitleLength = 0;
foreach (var choice in list)
{
var l = choice.Action != null && !string.IsNullOrEmpty(choice.Action.Title) ? choice.Action.Title.Length : choice.Value.Length;
if (l > maxTitleLength)
{
maxTitleLength = l;
}
}
// Determine list style
var supportsSuggestedActions = Channel.SupportsSuggestedActions(channelId, list.Count);
var supportsCardActions = Channel.SupportsCardActions(channelId, list.Count);
var maxActionTitleLength = Channel.MaxActionTitleLength(channelId);
var hasMessageFeed = Channel.HasMessageFeed(channelId);
var longTitles = maxTitleLength > maxActionTitleLength;
if (!longTitles && !supportsSuggestedActions && supportsCardActions)
{
// SuggestedActions is the preferred approach, but for channels that don't
// support them (e.g. Teams, Cortana) we should use a HeroCard with CardActions
return HeroCard(list, text, speak);
}
else if (!longTitles && supportsSuggestedActions)
{
// We always prefer showing choices using suggested actions. If the titles are too long, however,
// we'll have to show them as a text list.
return SuggestedAction(list, text, speak);
}
else if (!longTitles && list.Count <= 3)
{
// If the titles are short and there are 3 or less choices we'll use an inline list.
return Inline(list, text, speak, options);
}
else
{
// Show a numbered list.
return List(list, text, speak, options);
}
}
This is why you got the list if you provide more than 10 items.
Generally, it's a best practice to limit the number of buttons, more than 10 is huge. You may adapt your behaviour (grouping items / adding an additional level of selection by group for example)
Upvotes: 1