C# 如何解决FormFlow中值之间的依赖关系冲突

C# 如何解决FormFlow中值之间的依赖关系冲突,c#,botframework,formflow,C#,Botframework,Formflow,我正在使用带有FormFlow的MicrosoftBot框架让用户填写表单。 假设我的表单有两个字段: 国家 城市 所以我有两个枚举: public enum Country { France, Germany } public enum City { Paris, Berlin } 田野城市总是依赖田野国家,因为一个城市属于一个国家。 这意味着用户只能填写法国+巴黎或德国+柏林 我的表格: public class LocationForm { [Prompt(

我正在使用带有FormFlow的MicrosoftBot框架让用户填写表单。 假设我的表单有两个字段:

  • 国家
  • 城市
所以我有两个枚举:

public enum Country {
    France, Germany
}

public enum City {
    Paris, 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();
}
private静态格式BuildLocationForm()
{
返回新的FormBuilder()
.字段(名称(国家))
.Field(新FieldReflector(名称(位置形式.城市))
.SetDefine(异步(状态、字段)=>
{
开关(州、国家)
{
案例国家:法国:
field.RemoveValue(城市柏林);
打破
案例国家:德国:
field.RemoveValue(城市,巴黎);
打破
}
返回true;
})
.确认(异步(状态)=>
新PrompAttribute(
“您选择了{Country}和{City},对吗?{|}”))
.Build();
}
我不知道RemoveValue在这里的用法是否正确,感觉有点被黑客攻击了,但到目前为止它仍然有效

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

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

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

我想实现的是,无论何时通过确认对话框更改国家,用户都必须根据国家字段中的更改更改城市选择

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

我走错方向了吗? 如果没有对整个FormFlow实现进行黑客攻击,这是可能的吗

我将感谢任何帮助

提前谢谢

更新(附加信息):我尝试了Microsoft Find提供的三明治机器人示例,它似乎有相同的(错误)行为。
您可以额外获得一份(免费饼干/饮料)订购一英尺长的三明治时。确认后将长度更改为六英寸,您仍然有多余的,但只需支付六英寸。

您可以做的是,在
国家/地区
字段内,验证以前的选择和新选择是否相同;如果不清楚
城市的值,则会再次提示该城市。

同时将您的城市类型更改为
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
}
[可序列化]
公务舱位置表
{
[提示(“哪个国家?{|}”)]
公共国家?国家;
[提示(“哪个城市?{|}”)]
公共字符串城市;
公共静态表单BuildLocationForm()
{
返回新的FormBuilder()
.Field(新FieldReflector(名称(国家))
.SetValidate(异步(状态、响应)=>
{
var result=newvalidateResult{IsValid=true,Value=response};
//验证以检查当前国家/地区和以前选择的国家/地区是否相同,从而不会再次提示用户输入城市
if(state.country.ToString()!=response.ToString())
state.city=String.Empty;
返回结果;
}))
.Field(新FieldReflector(名称(城市))
//获取按钮的步骤SetType(null)
.SetType(空)
.SetDefine(异步(状态、字段)=>
{
//如果更改了国家/地区的选择,则应清除确认之前的任何值
field.RemoveValues();
开关(州、国家)
{
案例国家:法国:
领域
.AddDescription(name of(City.Berlin),name of(City.Berlin))
.AddTerms(name of(City.Berlin),name of(City.Berlin));
//添加更多说明和术语(如有)
打破
案例国家:德国:
领域
.AddDescription(name of(City.Paris),name of(City.Paris))
.AddTerms(name of(City.Paris),name of(City.Paris));
//添加更多说明和术语(如有)
打破
}
返回true;
}))
.AddRemainingFields()
.确认(异步(状态)=>
{
返回新的prompattribute($“您选择了{state.country}和{state.city},对吗?”+“{|}”);
})
.Build();
}
}
[可序列化]
公共枚举国家
{
法国、德国
}
[可序列化]
公共城市
{
巴黎,柏林
}
现在您有了预期的行为。如果国家/地区发生更改,城市将再次提示选择。如果用户说
进行确认,并且没有更改国家/地区,则选择上一个选择