如何解决 FormFlow 中值之间的依赖冲突

How to solve dependency conflicts between values within a FormFlow

我正在使用带有 FormFlow 的 Microsoft Bot Framework 让用户填写表单。 假设我的表单有两个字段:

所以我有两个枚举:

public enum Country {
    France, Germany
}

public enum City {
    Paris, Berlin
}

字段City总是依赖于字段Country,因为一个城市属于一个国家。 这意味着用户只能填写 France+ParisGermany+Berlin.

我的表格:

public class LocationForm
{
    [Prompt("Which country? {||}")]
    public Country? Country;

    [Prompt("Which city? {||}")]
    public City? City;
}

我的建造者:

private static IForm<LocationForm> BuildLocationForm()
{
    return new FormBuilder<LocationForm>()
        .Field(nameof(Country))
        .Field(new FieldReflector<LocationForm>(nameof(LocationForm.City))
                .SetDefine(async (state, field) =>
                {
                    switch (state.Country)
                    {
                        case Country.France:
                            field.RemoveValue(City.Berlin);
                            break;
                        case Country.Germany:
                            field.RemoveValue(City.Paris);
                            break;
                    }
                return true;
                })
        .Confirm(async (state) =>
                new PromptAttribute(
                    "You selected {Country} and {City}, is that correct? {||}"))
        .Build();
}

我不知道 RemoveValue 的用法在这里是否正确,感觉有点被黑了,但目前有效。

用户第一次填写表格时一切正常,用户只能select巴黎柏林 ] 取决于之前的 国家/地区 selected。 但是,当用户用 No 回答确认问题时,可以更改 CountryCity . 当用户随后将 CountryFrance 更改为 Germany 时,FormFlow 将询问:

You selected Germany and Paris, is that correct?

这显然不正确,但仍然可以回答

我想实现,无论何时通过确认对话框更改国家/地区,用户必须更改 城市 selection 取决于 Country 字段的变化。

我正在研究 SetNext 方法,但我找不到任何有用的东西。

我走错路了吗? 如果不绕过整个 FormFlow 实现,这甚至可能吗?

如有任何帮助,我将不胜感激!

提前致谢!

更新(附加信息):我尝试了 Microsoft 提供的 Sandwich Bot 示例 here,它似乎具有相同的(错误)行为。 订购 英尺长 三明治时,您将获得额外的(免费 cookie/drink)。将长度更改为 六英寸 确认后您还有多余的,但只需支付 六英寸.

您可以做的是,在 country 字段中,验证之前和新的选择是否相同;如果不清楚 city 的值,则会再次提示该城市。

同时将您的城市类型更改为 string,这样您就可以根据 country 的选择动态加载值,而不是使用 field.RemoveValue()(尽管这不是一个坏方法)

所以代码是:

[Serializable]
public class LocationForm
{
    [Prompt("Which country? {||}")]
    public Country? country;

    [Prompt("Which city? {||}")]
    public string city;

    public static IForm<LocationForm> BuildLocationForm()
    {
        return new FormBuilder<LocationForm>()
            .Field(new FieldReflector<LocationForm>(nameof(country))
                .SetValidate(async (state, response) =>
                {
                    var result = new ValidateResult { IsValid = true, Value = response };
                    //Validation to check if the current country and previous selected country are same so that user is not prompted again for city
                    if (state.country.ToString() != response.ToString())
                        state.city = String.Empty;
                    return result;
                }))
            .Field(new FieldReflector<LocationForm>(nameof(city))
                //To get buttons SetType(null)
                .SetType(null)
                .SetDefine(async (state, field) =>
                {
                    //Any previous value before the confirm should be cleared in case selection is changed for country
                    field.RemoveValues();
                    switch (state.country)
                    {
                        case Country.France:
                            field
                                    .AddDescription(nameof(City.Berlin), nameof(City.Berlin))
                                    .AddTerms(nameof(City.Berlin), nameof(City.Berlin));
                                    //Add more description and terms if any
                            break;
                        case Country.Germany:
                            field
                                    .AddDescription(nameof(City.Paris), nameof(City.Paris))
                                    .AddTerms(nameof(City.Paris), nameof(City.Paris));
                                    //Add more description and terms if any
                            break;
                    }
                    return true;
                }))
            .AddRemainingFields()
            .Confirm(async (state) =>
            {
                return new PromptAttribute($"You selected {state.country} and {state.city}, is that correct?" + "{||}");
            })
            .Build();
    }
}

[Serializable]
public enum Country
{
    France, Germany
}

[Serializable]
public enum City
{
    Paris, Berlin
}

现在您有了预期的行为。如果国家/地区发生变化,将再次提示选择城市。如果用户说 no 进行确认并且不更改国家/地区并选择先前选择的县本身,则不会再次提示城市,直接确认选择 CountryCity被提示。

模拟器响应