2

BuildForm 方法

        public static IForm<FAQConversation> BuildForm()
        {
            return new FormBuilder<FAQConversation>()
                .Field(new FieldReflector<FAQConversation>(nameof(Inquiry))
                    .SetValidate(AnswerInquiry)
                    .SetPrompt(new PromptAttribute("Okay, tell me what is your question. Enter \"back\" to go back to Products Selection."))
                    )
                .Build();
        }

验证方法

        private static async Task<ValidateResult> AnswerInquiry(FAQConversation state, object value)
        {
             var result = new ValidateResult();
             //somecode here
             if(testCase == false)
             {
                result.isValid = false;
                result.Feedback = "Try again";
             }
             else
             {
                result.isValid = true;
             }
             return result;
        }

当我的验证字段上的输入无效时,我的验证方法会返回反馈“再试一次”文本。但是,它会返回原始提示和反馈文本。

问题
如何删除重新验证字段的原始提示?

4

1 回答 1

1

虽然 FormFlow 确实提供了很多可定制性,但它背后的主要思想是为您自动化所有内容,这往往表明至少有些东西是内置的。

我了解您想要做的是在“重试”时禁用字段提示,也就是说,如果用户已经看到了字段提示并且他们输入了无效的内容,那么他​​们不应该看到提示再次。我可以在源代码中看到 FormFlow 并没有真正为“重试”提供特殊情况,并且当字段仍然未知时提示的行为是这些内置的东西之一。但是,您仍然可以做一些事情。

FormFlow 提供了一种(大部分未记录的)方法来替换所谓的“提示符”。您可以使用该Prompter()方法执行此操作,该方法需要一个PromptAsyncDelegate. 作为新提示器的起点,您可以在 FormBuilder 源代码中找到默认提示器:

_form._prompter = async (context, prompt, state, field) =>
{
    var preamble = context.MakeMessage();
    var promptMessage = context.MakeMessage();
    if (prompt.GenerateMessages(preamble, promptMessage))
    {
        await context.PostAsync(preamble);
    }
    await context.PostAsync(promptMessage);
    return prompt;
};

虽然默认提示器总是发布promptMessage,但您的替换可以用 if 语句围绕该行。这就留下了你的条件应该是什么的问题。我们已经确定 FormFlow 不包含任何重试的概念,因此您必须以某种方式在自己中构建它。您可以在 FAQConversation 的状态中包含一个布尔字段作为开关,或者您甚至可以使用 PrivateConversationData,因为提示器允许您访问 DialogContext。您可能会认为,当提示显示一次或 AnswerInquiryAsync 确定用户输入无效时关闭开关是一件简单的事情,但何时重新打开开关?如果用户输入“返回”并且您希望再次显示提示怎么办?

虽然您可能会找到一些方法来更准确地表示“重试时禁用提示”的逻辑,但我想出的最简单的解决方案是跟踪 FormFlow 生成的最后一条消息,然后跳过“再试一次”之后出现的第一条消息。” 它看起来像这样:

[Serializable]
public class FAQConversation
{
    public string Inquiry { get; set; }

    private string LastMessage { get; set; }

    private const string TRY_AGAIN = "Try again";

    public static IForm<FAQConversation> BuildForm()
    {
        return new FormBuilder<FAQConversation>()
            // This is an alternative way of using the Field() method but it works the same.
            .Field(nameof(Inquiry),
                "Okay, tell me what is your question. Enter \"back\" to go back to Products Selection.",
                validate: AnswerInquiryAsync)
            .Prompter(PromptAsync)
            .Build();
    }

    private static async Task<ValidateResult> AnswerInquiryAsync(FAQConversation state, object value)
    {
        var result = new ValidateResult();
        bool testCase = Equals(value, "true");  // Enter "true" to continue for testing purposes.

        if (testCase == false)
        {
            result.IsValid = false;
            // A constant should be used with strings that appear more than once in your code.
            result.Feedback = TRY_AGAIN;
        }
        else
        {
            result.IsValid = true;
            // A value must be provided or else the Field will not be populated.
            result.Value = value;
        }

        return result;
    }

    /// <summary>
    /// Here is the method we're using for the PromptAsyncDelegate.
    /// </summary>
    private static async Task<FormPrompt> PromptAsync(IDialogContext context, FormPrompt prompt,
        FAQConversation state, IField<FAQConversation> field)
    {
        var preamble = context.MakeMessage();
        var promptMessage = context.MakeMessage();

        if (prompt.GenerateMessages(preamble, promptMessage))
        {
            await context.PostAsync(preamble);
        }

        // Here is where we've made a change to the default prompter.
        if (state.LastMessage != TRY_AGAIN)
        {
            await context.PostAsync(promptMessage);
        }

        state.LastMessage = promptMessage.Text;

        return prompt;
    }
}
于 2018-08-21T21:40:02.727 回答