J'essaie de créer une boîte de dialogue dans laquelle je définis plusieurs étapes en cascade. Dans le cadre de cette boîte de dialogue, j'ai parfois besoin de revenir à l'étape précédente en cascade selon le choix de l'utilisateur. J'ai trouvé cette méthode:
await stepContext.ReplaceDialogAsync("Name of the dialog");
cependant, cette méthode réexécute toute la boîte de dialogue et ce n'est pas ce dont j'ai besoin.
En fait, les étapes de cascade que j'ai créées sont trois:
Mon code est:
public class ListAllCallsDialog : ComponentDialog
{
// Dialog IDs
private const string ProfileDialog = "ListAllCallsDialog";
/// <summary>
/// Initializes a new instance of the <see cref="ListAllCallsDialog"/> class.
/// </summary>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> that enables logging and tracing.</param>
public ListAllCallsDialog(ILoggerFactory loggerFactory)
: base(nameof(ListAllCallsDialog))
{
// Add control flow dialogs
var waterfallSteps = new WaterfallStep[]
{
ListAllCallsDialogSteps.ChoiceCallStepAsync,
ListAllCallsDialogSteps.ShowCallStepAsync,
ListAllCallsDialogSteps.EndDialog,
};
AddDialog(new WaterfallDialog(ProfileDialog, waterfallSteps));
AddDialog(new ChoicePrompt("cardPrompt"));
}
/// <summary>
/// Contains the waterfall dialog steps for the main dialog.
/// </summary>
private static class ListAllCallsDialogSteps
{
static int callListDepth = 0;
static List<string> Calls;
public static async Task<DialogTurnResult> ChoiceCallStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
await stepContext.Context.SendActivityAsync(
"Right now i'm in list all calls dialog",
cancellationToken: cancellationToken);
GetAllCalls();
return await stepContext.PromptAsync("cardPrompt", GenerateOptions(stepContext.Context.Activity, callListDepth), cancellationToken);
}
public static async Task<DialogTurnResult> ShowCallStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Get the text from the activity to use to show the correct card
var text = stepContext.Context.Activity.Text.ToLowerInvariant();
if(text == "Show older")
//Go back to the first step
else if(text == "Show earlier")
//Go back to the first step
else
await stepContext.Context.SendActivityAsync(
"The call you choose is : " + text.ToString(),
cancellationToken: cancellationToken);
return await stepContext.ContinueDialogAsync();
}
public static async Task<DialogTurnResult> EndDialog(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
await stepContext.Context.SendActivityAsync(
"Getting back to the parent Dialog",
cancellationToken: cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
/// <summary>
/// Creates options for a <see cref="ChoicePrompt"/> so the user may select an option.
/// </summary>
/// <param name="activity">The message activity the bot received.</param>
/// <returns>A <see cref="PromptOptions"/> to be used in a Prompt.</returns>
/// <remarks>Related type <see cref="Choice"/>.</remarks>
private static PromptOptions GenerateOptions(Activity activity, int callListDepth)
{
// Create options for the Prompt
var options = new PromptOptions()
{
Prompt = activity.CreateReply("Please choose a call from the list below"),
Choices = new List<Choice>(),
};
for(int i=10*callListDepth; i <= 10 * (callListDepth + 1); i++)
{
if (Calls.ElementAtOrDefault(i) != null)
options.Choices.Add(new Choice() { Value = Calls[i] });
}
options.Choices.Add(new Choice() { Value = "Show older" });
if(callListDepth!=0)
options.Choices.Add(new Choice() { Value = "Show earlier" });
return options;
}
private static void GetAllCalls()
{
//List of all calls found
for (int i = 0; i < 30; i++)
Calls.Add("Call" + i.ToString());
}
}
}
Quelqu'un peut-il me montrer comment faire cela, s'il vous plaît?
Je ne suis pas sûr, si c'est la bonne et efficace façon de le faire, mais vous pouvez expérimenter avec la propriété State
de la context.ActiveDialog
dans votre Task<DialogTurnResult>
fonction.
context.ActiveDialog.State["stepIndex"] = (int)context.ActiveDialog.State["stepIndex"] -2;
Les dialogues en cascade n'étaient pas conçus avec l'idée de `` reculer '' pour les traverser, bien que je puisse voir la nécessité éventuelle de le faire. La seule solution que j'ai trouvée est de briser votre cascade en petites "mini" cascades et de les emboîter dans une plus grande cascade.
// define and add waterfall dialogs (main)
WaterfallStep[] welcomeDialogSteps = new WaterfallStep[]
{
MainDialogSteps.PresentMenuAsync,
MainDialogSteps.ProcessInputAsync,
MainDialogSteps.RepeatMenuAsync,
};
Puis dans MainDialogSteps.ProcessInputAsync:
public static async Task<DialogTurnResult> ProcessInputAsync(
WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
var choice = (FoundChoice)stepContext.Result;
var dialogId = Lists.WelcomeOptions[choice.Index].DialogName;
return await stepContext.BeginDialogAsync(dialogId, null, cancellationToken);
}
Cela permet aux utilisateurs de démarrer de nouvelles boîtes de dialogue toujours dans la pile de boîtes de dialogue principale. Une de mes options que j'ai offert était une invite d'une liste de numéros de téléphone:
WaterfallStep[] phoneChoiceDialogSteps = new WaterfallStep[]
{
PhoneChoicePromptSteps.PromptForPhoneAsync,
PhoneChoicePromptSteps.ConfirmPhoneAsync,
PhoneChoicePromptSteps.ProcessInputAsync,
};
Add(new WaterfallDialog(Dialogs.PhonePrompt, phoneChoiceDialogSteps));
Et enfin, dans PhoneChoicePromptSteps.ProcessInputAsync, j'ai autorisé la sélection de `` non '' de la confirmation à ReplaceDialogAsync et réinitialisé efficacement cette petite cascade, sans affecter le reste de la cascade globale:
public static async Task<DialogTurnResult> ProcessInputAsync(
WaterfallStepContext stepContext,
CancellationToken cancellationToken)
{
if ((bool)stepContext.Result)
{
await stepContext.Context.SendActivityAsync(
$"Calling {stepContext.Values[Outputs.PhoneNumber]}",
cancellationToken: cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
else
{
return await stepContext.ReplaceDialogAsync(Dialogs.PhonePrompt, null, cancellationToken);
}
}