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;
Это будет означать, что если базовые данные изменятся между первым поворотом приглашения и вторым, выбор все равно будет действительным.