我不能让RepromptDialogAsync()
工作。我是这样做的。当选择对话框b
时,它应该重新提示选择提示,因为对话框B
还没有准备好。但是当选择对话框b
时,它什么都不做。我做错了吗?我在文档上找不到任何RepromptDialogAsync()
教程。谢谢!
主要代码:
public class MainDialog : ComponentDialog
{
private const string InitialId = "mainDialog";
private const string ChoicePrompt = "choicePrompt";
private const string DialogAId = "dialogAId";
public MainDialog(string dialogId)
: base(dialogId)
{
InitialDialogId = InitialId;
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
FourthStepAsync
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new DialogA(DialogAId));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
ChoicePrompt,
new PromptOptions
{
Prompt = MessageFactory.Text($"Here are your choices:"),
Choices = new List<Choice>
{
new Choice
{
Value = "Open Dialog A",
},
new Choice
{
Value = "Open Dialog B",
},
},
RetryPrompt = MessageFactory.Text($"Please choose one of the options."),
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var response = (stepContext.Result as FoundChoice)?.Value.ToLower();
if (response == "open dialog a")
{
return await stepContext.BeginDialogAsync(DialogAId, cancellationToken: cancellationToken);
}
if (response == "open dialog b")
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Dialog B is not ready need to reprompt previous step."));
await stepContext.RepromptDialogAsync();
}
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
// do something else
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> FourthStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
// what is the best way to end this?
// return await stepContext.ReplaceDialogAsync(InitialId);
return await stepContext.EndDialogAsync();
}
我将在这个答案中解决几个问题:
RepromptDialogAsync()
calls reprompt
on the currently active dialog, but is meant to be used with Prompts that have a reprompt
behavior。 ChoicePrompt
确实有reprompt
选项,但不打算在这种情况下使用。相反,你会调用你的提示,在OnTurnAsync
中验证响应,并在必要时调用dc.RepromptDialogAsync()
。
你的OnTurnAsync
可能看起来像这样:
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
var activity = turnContext.Activity;
var dc = await Dialogs.CreateContextAsync(turnContext);
if (activity.Type == ActivityTypes.Message)
{
if (activity.Text.ToLower() == "open dialog b")
{
await dc.RepromptDialogAsync();
};
...
话虽这么说,我根本不会使用RepromptDialogAsync()
作为你的用例。而是,使用以下选项之一:
ReplaceDialogAsync()
最简单的选择是替换:
await stepContext.RepromptDialogAsync();
有:
return await stepContext.ReplaceDialogAsync(InitialId);
这将启动你的“mainDialog”结束。在你的例子中,这很好,因为你从第二步重新开始到第一步。
ChoicePrompt
会自动验证用户是否使用有效选项进行响应,但您可以传入自己的自定义验证器。就像是:
AddDialog(new ChoicePrompt(choicePrompt, ValidateChoice));
...
private async Task<bool> ValidateChoice(PromptValidatorContext<FoundChoice> promptContext, CancellationToken cancellationToken)
{
if (promptContext.Recognized.Value.Value.ToLower() == "open dialog b")
{
return false;
}
else
{
return true;
}
}
但实际上,如果没有准备好,您不应该提示用户选择“对话框b”。相反,你可以这样做:
var choices = new List<Choice>
{
new Choice
{
Value = "Open Dialog A",
}
};
if (bIsReady)
{
choices.Add(new Choice
{
Value = "Open Dialog B",
});
};