botbuilder v 4, динамическая адаптивная карта с выпадающим списком и вводом значений по запросу

Я использую ms botbuilder v 4 Я использую webcontrol, webchat.js, последний, реагировать. Дело довольно тривиально: я хочу показать список возможных значений в раскрывающемся списке, значения будут динамическими (приходит из API, мне нужны Названия и Значения (Ids) там. Затем, когда пользователь выбирает какой-то элемент и нажимает кнопку ОК, я хочу получить значение (Id) и работать с ним далее. Как я понял, пока единственным способом показать раскрывающийся список является использование адаптивных карт, в v3 была возможность использовать адаптивные карты в приглашениях, и это также запланировано на следующую версию: https://github.com/Microsoft/botbuilder-dotnet/issues/1170 Но пока здесь объясняется только wraround для этого: https://github.com/Microsoft/botbuilder-dotnet/issues/614, с просто списком строк, все работает нормально, но если я хочу сохранить пары значений ключей (для идентификаторов), я не могу этого сделать, потому что выбор в PromptOptions принимает только список строк (будет показано ниже). Так что единственный способ, которым я сейчас пользуюсь, - это сохранить всю коллекцию значений, а после получения результата пойти и найти его идентификатор. Есть ли более удобное решение для этого? Вот код:

var choicesInputs = _teams.Select(s => new AdaptiveChoice { Title = s.Value, Value = s.Value}).ToList();

var card = new AdaptiveCard
{
    Version = new AdaptiveSchemaVersion(1, 0),
    Body =
    {
        new AdaptiveTextBlock("Select a team to assign your ticket"),
        new AdaptiveChoiceSetInput
        {
            Choices = choicesInputs,
            Id = "setId",
            Style = AdaptiveChoiceInputStyle.Compact,
            IsMultiSelect = false
        }
    },
    Actions = new List<AdaptiveAction>
    {
        new AdaptiveSubmitAction
        {
            Title = "Ok",
            Type = "Action.Submit"
        }
    }
};

signInPhoneState.Teams = _teams;

return await stepcontext.PromptAsync(
    "SelectGroupCardDialog",
    new PromptOptions
    {
            Choices = ChoiceFactory.ToChoices(_teams.Select(pair => pair.Value).ToList()),
        Prompt = (Activity) MessageFactory.Attachment(new Attachment
        {
            ContentType = AdaptiveCard.ContentType,
            Content = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(card))
        })
    },
    cancellationtoken);

// . . .

var selectedTeamId = signInPhoneState.Teams.FirstOrDefault(pair => pair.Value == sel).Key;

Быстрый побочный вопрос (но связанный с терминами, которые я использую для временного решения): Какой самый простой способ сохранить некоторую переменную через диалог? Если я правильно помню, в v3 это было так же просто, как пометить значение как public и пометить диалог как сериализуемый, и все, теперь, когда я его получил, вам нужно создать специальный аксессор для каждого диалога, дублировать свойство и управлять его состоянием, это правильно? Спасибо

1 ответ

Решение

У вас есть словарь с идентификаторами команд в качестве ключей и именами команд в качестве значений. Вы используете имена команд в качестве значений для адаптивного набора выбора, который используется в приглашении, и, в свою очередь, после запроса вы извлекаете идентификатор команды из словаря, используя имя команды. Вы хотите более удобный вариант.

Вариант 1. Если вы согласны с текущими настройками сохранения словаря

При доступе к данным в словаре более эффективно получить доступ к значению с помощью ключа, чем наоборот. Это то, для чего словари, в конце концов. Таким образом, вместо использования названий команд в качестве значений в выбранном наборе, вы можете использовать идентификаторы команд.

var choicesInputs = _teams.Select(s => new AdaptiveChoice { Title = s.Value, Value = s.Key }).ToList();

// . . .

signInPhoneState.Teams.TryGetValue(sel, out string selectedTeamName);

Это будет означать, что если словарь создается из какого-либо внешнего источника, который может быть изменен, название группы будет как можно более актуальным.

Вариант 2: если вы не хотите зависеть от словаря для следующего хода

Вы можете сохранить как идентификатор команды, так и название команды в значении выбора.

var choicesInputs = _teams.Select(s => new AdaptiveChoice { Title = s.Value, Value = JsonConvert.SerializeObject(s) }).ToList();

// . . .

var pair = JsonConvert.DeserializeObject<KeyValuePair<string, string>>(sel);
var selectedTeamId = pair.Key;
var selectedTeamName = pair.Value;

Это будет означать, что если базовые данные изменятся между первым поворотом приглашения и вторым, выбор все равно будет действительным.

Другие вопросы по тегам