You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bot Framework v4 Web渠道下自适应卡片级联下拉菜单实现咨询

Implementing Cascading Dropdowns in Adaptive Cards (Bot Framework v4, Web Channel)

Hey Sanjeev, great question! Cascading dropdowns in Adaptive Cards for Bot Framework v4 on the Web channel are totally doable—they just require a mix of Adaptive Card design and bot-side logic since Adaptive Cards themselves don’t natively support cascading out of the box. Let me walk you through the core steps:

Step 1: Create the Initial Adaptive Card with the First Dropdown

Start by designing a card that includes your first dropdown (e.g., "Country"). This card will trigger a bot action when the user selects an option.

Here’s a sample JSON for the initial card:

{
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "TextBlock",
      "text": "Select your Country",
      "weight": "Bolder",
      "size": "Medium"
    },
    {
      "type": "Input.ChoiceSet",
      "id": "countrySelect",
      "choices": [
        { "title": "USA", "value": "usa" },
        { "title": "Canada", "value": "canada" },
        { "title": "UK", "value": "uk" }
      ],
      "placeholder": "Choose a country"
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Next",
      "data": { "action": "loadStates" }
    }
  ]
}

Step 2: Handle the First Selection in Your Bot

When the user submits the first dropdown, your bot needs to capture the selected value, fetch the corresponding options for the second dropdown (e.g., "States" for the selected country), and send a new Adaptive Card with the second dropdown.

Example in C#:

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var activityValue = turnContext.Activity.Value as JObject;
    if (activityValue != null && activityValue["action"]?.ToString() == "loadStates")
    {
        var selectedCountry = activityValue["countrySelect"]?.ToString();
        // Fetch states based on country (replace with your data source)
        var stateChoices = GetStatesForCountry(selectedCountry);

        // Create a new Adaptive Card with state dropdown
        var stateCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0))
        {
            Body = {
                new AdaptiveTextBlock { Text = $"Select your State in {selectedCountry}", Weight = AdaptiveTextWeight.Bolder, Size = AdaptiveTextSize.Medium },
                new AdaptiveChoiceSetInput { Id = "stateSelect", Choices = stateChoices.Select(s => new AdaptiveChoice { Title = s, Value = s }).ToList() }
            },
            Actions = { new AdaptiveSubmitAction { Title = "Submit", Data = new { action = "submitSelection" } } }
        };

        await turnContext.SendActivityAsync(MessageFactory.Attachment(new Attachment
        {
            ContentType = AdaptiveCard.ContentType,
            Content = stateCard
        }), cancellationToken);
        return;
    }

    // Handle initial message or other actions
    await turnContext.SendActivityAsync(MessageFactory.Attachment(InitialCountryCard()), cancellationToken);
}

private List<string> GetStatesForCountry(string country)
{
    switch(country)
    {
        case "usa": return new List<string> { "California", "Texas", "New York" };
        case "canada": return new List<string> { "Ontario", "Quebec", "British Columbia" };
        case "uk": return new List<string> { "England", "Scotland", "Wales" };
        default: return new List<string>();
    }
}

Example in Node.js:

this.onMessage(async (context, next) => {
    const activityValue = context.activity.value;
    if (activityValue && activityValue.action === 'loadStates') {
        const selectedCountry = activityValue.countrySelect;
        const stateChoices = getStatesForCountry(selectedCountry);

        // Build state card JSON
        const stateCard = {
            type: "AdaptiveCard",
            version: "1.0",
            body: [
                { type: "TextBlock", text: `Select your State in ${selectedCountry}`, weight: "Bolder", size: "Medium" },
                {
                    type: "Input.ChoiceSet",
                    id: "stateSelect",
                    choices: stateChoices.map(s => ({ title: s, value: s }))
                }
            ],
            actions: [{ type: "Action.Submit", title: "Submit", data: { action: "submitSelection" } }]
        };

        await context.sendActivity({
            attachments: [{
                contentType: "application/vnd.microsoft.card.adaptive",
                content: stateCard
            }]
        });
        return;
    }

    // Send initial country card
    await context.sendActivity({
        attachments: [{ contentType: "application/vnd.microsoft.card.adaptive", content: initialCountryCard() }]
    });
    await next();
});

function getStatesForCountry(country) {
    switch(country) {
        case 'usa': return ['California', 'Texas', 'New York'];
        case 'canada': return ['Ontario', 'Quebec', 'British Columbia'];
        case 'uk': return ['England', 'Scotland', 'Wales'];
        default: return [];
    }
}

Step 3: Handle the Final Submission

Once the user selects the second dropdown and submits, your bot can capture both values and process them as needed. For example, in C#:

else if (activityValue["action"]?.ToString() == "submitSelection")
{
    var selectedCountry = activityValue["countrySelect"]?.ToString(); // If you persisted this, or pass it in the submit data
    var selectedState = activityValue["stateSelect"]?.ToString();
    await turnContext.SendActivityAsync(MessageFactory.Text($"You selected {selectedState}, {selectedCountry}!"), cancellationToken);
}

Key Notes

  • Persist Context: If you need to retain the first selection for the final submit, you can either store it in bot state (like UserState) or include it in the second card’s submit data (e.g., add country: selectedCountry to the submit action’s data).
  • Web Channel Compatibility: This approach works seamlessly on the Web channel since it relies on standard Adaptive Card submit actions and bot-side processing—no special channel-specific hacks needed.
  • Dynamic Data: Replace the hardcoded state lists with calls to your actual data source (API, database, etc.) for real-world use.

内容的提问来源于stack exchange,提问作者Sanjeev Gautam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:59:06