Dileep Kanta
Dileep Kanta

Reputation: 51

How to add more than 10 buttons for ChoicePrompt Bot framework V4 c#

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

Answers (2)

Kyle Delaney
Kyle Delaney

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:

Facebook Messenger

In Skype it will look like this:

Skype

Upvotes: 2

Nicolas R
Nicolas R

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

Related Questions