如何在之前的 BotChat 对话中禁用输入/提交按钮操作 - Microsoft Bot Framework (C#) 中的 AdaptiveCards
问问题
3744 次
1 回答
3
我想象您想向用户显示一张只使用一次的卡片,例如本例中所示的日历提醒。
机器人主要意味着具有与人类相同的通道访问权限,因此它们无法返回并修改已发送的消息(除非特定通道允许像 Slack 那样进行编辑)。虽然您无法禁用卡片中已经包含在对话历史记录中的按钮,但您可以更改机器人响应该卡片生成的消息的方式。您要做的是跟踪按钮是否已被单击,然后在随后单击该按钮时做出不同的响应。
下面是一些可以以三种方式响应消息的 Dialog 代码的基本示例。如果您键入任何消息并将其发送到机器人,它将显示一张带有按钮的卡片。如果你点击按钮,它会说“你做到了!” 以及您单击的按钮的 ID。如果您再次单击相同的按钮,它将显示“您已经这样做了!” 再次附上身份证。
/// <summary>
/// You'll want a label like this to identify the activity
/// that gets generated in response to your submit button.
/// </summary>
private const string DO_SOMETHING = "DoSomething";
/// <summary>
/// This is passed into context.Wait() in your StartAsync method.
/// </summary>
private async Task MessageReceivedAsync(IDialogContext context,
IAwaitable<IMessageActivity> result)
{
var msg = await result;
if (!string.IsNullOrWhiteSpace(msg.Text))
{
// If msg.Text isn't null or white space then that means the user
// actually typed something, and we're responding to that with a card.
var reply = context.MakeMessage();
var attachment = MakeAdaptiveCardAttachment();
reply.Attachments.Add(attachment);
await context.PostAsync(reply);
}
else
{
// If the user didn't type anything then this could be an activity
// that was generated by your submit button. But we want to make sure
// it is by checking msg.Value.
dynamic value = msg.Value;
try
{
// If value doesn't have a type then this will throw a RuntimeBinderException
if (value != null && value.type == DO_SOMETHING)
{
string id = value.id;
// Check the ID to see if that particular card has been clicked before.
if (!context.PrivateConversationData.ContainsKey(id))
{
// This is how your bot will keep track of what's been clicked.
context.PrivateConversationData.SetValue(id, true);
await context.PostAsync("You did it! " + id);
}
else
{
await context.PostAsync("You already did that! " + id);
}
}
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
// Respond to messages that don't have values with a type (or id).
}
}
context.Wait(MessageReceivedAsync);
}
private static Attachment MakeAdaptiveCardAttachment()
{
var card = new AdaptiveCard();
// We need to identify this specific card if we want to allow multiple
// instances of the card to be clicked.
// A timestamp could work but a GUID will do.
var cardId = Guid.NewGuid().ToString();
card.Body.Add(new TextBlock() { Text = cardId });
card.Actions.Add(new SubmitAction()
{
Title = "Do something",
// The data we put inside this action will persist.
// I've found setting DataJson to be more reliable than using the Data property.
// Note that if your WebApiConfig.cs has a CamelCasePropertyNamesContractResolver
// (which is a default) and you use capitalized (Pascal case) identifiers,
// they may be converted to camel case and you won't be able to retrieve
// the data with the same identifiers.
DataJson = JsonConvert.SerializeObject(new
{
// We need a type to differentiate this action from other actions.
type = DO_SOMETHING,
// We need an id to differentiate this card from other cards.
id = cardId,
}),
});
return new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card,
};
}
这是 Bot Framework Emulator 中的样子。请注意,即使您单击了一张卡片并且无法从该卡片获得第一个响应,您仍然可以从另一张卡片获得第一个响应。
于 2018-08-09T19:35:20.493 回答