2

我正在使用带有 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的用法在这里是否正确,感觉有点被黑了,但到目前为止它仍然有效。

用户第一次填写表格时一切正常,用户只能根据之前选择的国家/地区选择巴黎柏林。但是,当用户用No回答确认问题时,可以更改CountryCity。当用户然后将国家法国更改为德国时,FormFlow 将询问:

你选择了德国和巴黎,对吗?

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

我想实现的是,每当通过确认对话框更改国家/地区时,用户也必须根据国家/地区字段中的更改来更改城市选择。

我在玩SetNext方法,但我想不出任何有用的东西。

我在这里走错了吗?如果不破解整个 FormFlow 实现,这是否可能?

我将不胜感激任何帮助!

提前致谢!

更新(附加信息):我尝试了微软在此处找到的 Sandwich Bot 示例,它似乎具有相同的(错误)行为。订购一英尺长的三明治时,您将获得额外的(免费饼干/饮料) 。确认后将长度更改为六英寸,您仍然有多余的,但只需支付六英寸

4

1 回答 1

1

您可以做的是,在该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提示。

模拟器响应 在此处输入图像描述

于 2018-04-16T16:43:29.850 回答