如何在上一次BotChat对话中禁用输入/提交按钮操作-Microsoft Bot Framework(C#)中的AdaptiveCards
答案 0 :(得分:2)
我在想您要向用户显示只能使用一次的卡片,例如this example中显示的日历提醒。
大多数情况下,漫游器都具有与人类相同的访问通道的权限,因此它们无法返回并修改已发送的消息(除非特定的通道允许像Slack一样进行编辑)。虽然您不能禁用对话历史记录中已经包含的卡片中的按钮,但是您可以更改漫游器对该卡片生成的消息的响应方式。您要做的就是跟踪是否已单击某个按钮,然后在随后单击该按钮时做出不同的反应。
这是一些可以以三种方式响应消息的对话框代码的基本示例。如果您键入任何消息并将其发送到机器人,它将显示带有按钮的卡。如果单击该按钮,它将显示“您完成了!”。以及您单击的按钮的ID。如果再次单击同一按钮,则会显示“您已经这样做了!”。再次附加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中的外观。请注意,即使您单击了一张卡片后仍无法从该卡片获得第一响应,仍然可以从另一张卡片获得第一响应。