C# 未调用框架恢复对话框
C# 未调用框架恢复对话框,c#,botframework,C#,Botframework,我在botframework V4中的组件对话框出现问题 我正在使用一个根对话框,其中包含一个WaterWallDialog和一个Setupdialog。初始对话框是设置对话框。像这样: public RootDialog(SetupDialog setupDialog) : base(nameof(RootDialog)) { AddDialog(setupDialog); AddDialog(new Te
我在botframework V4中的组件对话框出现问题 我正在使用一个根对话框,其中包含一个WaterWallDialog和一个Setupdialog。初始对话框是设置对话框。像这样:
public RootDialog(SetupDialog setupDialog)
: base(nameof(RootDialog))
{
AddDialog(setupDialog);
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
ProcessStep
}));
InitialDialogId = nameof(SetupDialog);
}
在设置对话框中,我询问一些值。如果设置对话框继续,我将检查该值,如果它符合我的要求,我将结束对话框
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default)
{
if (!int.TryParse(outerDc.Context.Activity.Text, out var recursions))
{
return outerDc.PromptAsync(nameof(TextPrompt), new PromptOptions()
{
Prompt = MessageFactory.Text($"{outerDc.Context.Activity.Text} konnte nicht in eine Zahl konvertiert werden.")
});
}
return outerDc.EndDialogAsync(recursions);
}
public override Task continuedialgasync(DialogContext outerDc,CancellationToken CancellationToken=default)
{
if(!int.TryParse(outerDc.Context.Activity.Text,out-var递归))
{
返回outerDc.PromptAsync(nameof(TextPrompt),newpromptoptions()
{
Prompt=MessageFactory.Text($“{outerDc.Context.Activity.Text}konnte nicht in eine Zahl konvertiert werden.”)
});
}
返回outerDc.EndDialogAsync(递归);
}
如果我像这样结束对话框,不应该在RootDialog中调用ResumeDialog吗
下面是整个对话框:
public class RootDialog : ComponentDialog
{
private int recursions;
public RootDialog(SetupDialog setupDialog)
: base(nameof(RootDialog))
{
AddDialog(setupDialog);
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
ProcessStep
}));
InitialDialogId = nameof(SetupDialog);
}
public async Task<DialogTurnResult> ProcessStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Process step in root dialog")
});
if(Dialogs.Find(nameof(RecursiveDialog)) == null)
{
AddDialog(new RecursiveDialog(new DialogSet(), recursions));
}
if (recursions > 0)
{
return await stepContext.BeginDialogAsync(nameof(RecursiveDialog));
}
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Recursion lower or eqaul 0")
});
}
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default)
{
var dialogContext = CreateChildContext(outerDc);
await dialogContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Begin root dialog")
});
return await base.BeginDialogAsync(outerDc, options, cancellationToken);
}
public override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
if(innerDc.ActiveDialog != null)
{
return await innerDc.ContinueDialogAsync();
}
return await base.OnContinueDialogAsync(innerDc, cancellationToken);
}
public override async Task<DialogTurnResult> ResumeDialogAsync(DialogContext outerDc, DialogReason reason, object result = null, CancellationToken cancellationToken = default)
{
recursions = Convert.ToInt32(result);
await outerDc.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text($"Resume root dialog with recursion value {recursions}")
});
return await outerDc.BeginDialogAsync(nameof(WaterfallDialog));
}
}
公共类RootDialog:ComponentDialog
{
私有int递归;
公共根对话框(设置对话框设置对话框)
:base(nameof(RootDialog))
{
AddDialog(setupDialog);
AddDialog(新建文本提示(名称)(文本提示));
AddDialog(新建WaterWallDialog)(名称(WaterWallDialog),新建WaterWallStep[]
{
过程步骤
}));
InitialDialogId=nameof(SetupDialog);
}
公共异步任务ProcessStep(WaterWallStepContext stepContext,CancellationToken CancellationToken)
{
等待stepContext.PromptAsync(nameof(TextPrompt),新PromptOptions
{
Prompt=MessageFactory.Text(“根对话框中的处理步骤”)
});
if(Dialogs.Find(nameof(RecursiveDialog))==null)
{
AddDialog(新建RecursiveDialog(新建DialogSet(),递归));
}
如果(递归>0)
{
return wait-stepContext.BeginDialogAsync(nameof(RecursiveDialog));
}
return wait stepContext.PromptAsync(nameof(TextPrompt)),new PromptOptions
{
Prompt=MessageFactory.Text(“递归下限或eqaul 0”)
});
}
公共重写异步任务BeginDialogAsync(DialogContext outerDc,对象选项=null,CancellationToken CancellationToken=default)
{
var dialogContext=CreateChildContext(outerDc);
等待dialogContext.PromptAsync(nameof(TextPrompt)),新PromptOptions
{
Prompt=MessageFactory.Text(“开始根对话框”)
});
return wait base.BeginDialogAsync(outerDc、options、cancellationToken);
}
公共覆盖异步任务OnContinueDialogAsync(DialogContext innerDc,CancellationToken CancellationToken=default)
{
如果(innerDc.ActiveDialog!=null)
{
return wait innerDc.ContinueDialogAsync();
}
返回wait base.OnContinueDialogAsync(innerDc,cancellationToken);
}
公共覆盖异步任务ResumeDialogAsync(DialogContext-outerDc,DialogReason-reason,对象结果=null,CancellationToken CancellationToken=default)
{
递归=Convert.ToInt32(结果);
等待outerDc.PromptAsync(nameof(TextPrompt)),新建PromptOptions
{
Prompt=MessageFactory.Text($“使用递归值{recursions}恢复根对话框”)
});
return wait outerDc.BeginDialogAsync(nameof(waterwalldialog));
}
}
设置对话框:
public class SetupDialog : ComponentDialog
{
public SetupDialog()
: base(nameof(SetupDialog))
{
AddDialog(new TextPrompt(nameof(TextPrompt)));
}
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default)
{
if (!int.TryParse(outerDc.Context.Activity.Text, out var recursions))
{
return outerDc.PromptAsync(nameof(TextPrompt), new PromptOptions()
{
Prompt = MessageFactory.Text($"{outerDc.Context.Activity.Text} konnte nicht in eine Zahl konvertiert werden.")
});
}
return outerDc.EndDialogAsync(recursions);
}
public override Task<DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options, CancellationToken cancellationToken = default)
{
return innerDc.PromptAsync(nameof(TextPrompt), new PromptOptions()
{
Prompt = MessageFactory.Text("Wie viel rekursionen sollen erstellt werden?")
});
}
}
公共类设置对话框:组件对话框
{
公共设置对话框()
:base(名称(设置对话框))
{
AddDialog(新建文本提示(名称)(文本提示));
}
公共覆盖任务ContinueDialogAsync(DialogContext outerDc,CancellationToken CancellationToken=default)
{
if(!int.TryParse(outerDc.Context.Activity.Text,out-var递归))
{
返回outerDc.PromptAsync(nameof(TextPrompt),newpromptoptions()
{
Prompt=MessageFactory.Text($“{outerDc.Context.Activity.Text}konnte nicht in eine Zahl konvertiert werden.”)
});
}
返回outerDc.EndDialogAsync(递归);
}
公共覆盖任务OnBeginDialogAsync(DialogContext innerDc,对象选项,CancellationToken CancellationToken=default)
{
返回innerDc.PromptAsync(nameof(TextPrompt),newpromptoptions()
{
Prompt=MessageFactory.Text(“您觉得如何?”
});
}
}
因此,我得到了要触发的ResumeDialog方法
要触发ResumeDialog方法,结束的对话框和要恢复的对话框必须位于同一个对话框堆栈上
我的场景是BotDialogContext[RootDialog]->RootDialogContext[SetupDialog],但我需要类似于BotDialogContext[RootDialog,SetupDialog]的上下文
问题之一是,您启动的每个ComponentDialog都会创建自己的DialogContext。因此,如果在对话框中开始一个对话框,它会被推到内部DialogContext的堆栈上,依此类推。但是ResumeDialog方法的描述是
当父对话框堆栈上的子对话框完成此回合时调用,将控制权返回到此对话框组件
要在父对话框堆栈上放置子对话框,必须在外部对话框上下文上调用BeginDialog方法。此上下文还需要在其对话框集中设置“子对话框”
以下是我的例子:
RootDialog.cs:
public class RootDialog : ComponentDialog
{
private int recursions;
public RootDialog(SetupDialog setupDialog)
: base(nameof(RootDialog))
{
AddDialog(setupDialog);
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
ProcessStep
}));
InitialDialogId = nameof(SetupDialog);
}
public async Task<DialogTurnResult> ProcessStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Process step in root dialog")
});
if(Dialogs.Find(nameof(RecursiveDialog)) == null)
{
AddDialog(new RecursiveDialog(new DialogSet(), recursions));
}
if (recursions > 0)
{
return await stepContext.BeginDialogAsync(nameof(RecursiveDialog));
}
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Recursion lower or eqaul 0")
});
}
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default)
{
if (true)
{
return await outerDc.BeginDialogAsync(nameof(SetupDialog));
}
var dialogContext = CreateChildContext(outerDc);
await dialogContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text("Begin root dialog")
});
return await base.BeginDialogAsync(outerDc, options, cancellationToken);
}
protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
if(innerDc.ActiveDialog != null)
{
return await innerDc.ContinueDialogAsync();
}
return await base.OnContinueDialogAsync(innerDc, cancellationToken);
}
public override async Task<DialogTurnResult> ResumeDialogAsync(DialogContext outerDc, DialogReason reason, object result = null, CancellationToken cancellationToken = default)
{
recursions = Convert.ToInt32(result);
await outerDc.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = MessageFactory.Text($"Resume root dialog with recursion value {recursions}")
});
return await outerDc.BeginDialogAsync(nameof(WaterfallDialog));
}
}
public class SetupDialog : ComponentDialog
{
public SetupDialog()
: base(nameof(SetupDialog))
{
AddDialog(new TextPrompt(nameof(TextPrompt)));
}
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default)
{
if (!int.TryParse(outerDc.Context.Activity.Text, out var recursions))
{
return outerDc.PromptAsync(nameof(TextPrompt), new PromptOptions()
{
Prompt = MessageFactory.Text($"{outerDc.Context.Activity.Text} konnte nicht in eine Zahl konvertiert werden.")
});
}
return outerDc.EndDialogAsync(recursions);
}
public override Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default)
{
return base.BeginDialogAsync(outerDc, options, cancellationToken);
}
protected override Task<DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options, CancellationToken cancellationToken = default)
{
return innerDc.PromptAsync(nameof(TextPrompt), new PromptOptions()
{
Prompt = MessageFactory.Text("Wie viel rekursionen sollen erstellt werden?")
});
}
}
公共类RootDialog:ComponentDialog
{
私有int递归;
公共根对话框(Setu)
public class DialogBot<T> : ActivityHandler
where T : Dialog
{
protected readonly DialogSet Dialogs;
protected readonly BotState ConversationState;
protected readonly BotState UserState;
protected readonly ILogger Logger;
public DialogBot(ConversationState conversationState, UserState userState, IEnumerable<Dialog> dialogs, ILogger<DialogBot<T>> logger)
{
ConversationState = conversationState;
UserState = userState;
Logger = logger;
Dialogs = new DialogSet(conversationState.CreateProperty<DialogState>(nameof(DialogState)));
foreach(var dialog in dialogs)
{
Dialogs.Add(dialog);
}
}
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
await base.OnTurnAsync(turnContext, cancellationToken);
// Save any state changes that might have occured during the turn.
await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
}
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
Logger.LogInformation("Running dialog with Message Activity.");
var dc = await Dialogs.CreateContextAsync(turnContext, cancellationToken).ConfigureAwait(false);
if (dc.ActiveDialog != null)
{
await dc.ContinueDialogAsync();
}
else
{
// Run the Dialog with the new message Activity.
await dc.BeginDialogAsync(typeof(T).Name, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
}
}
}