如何解决 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+Paris 或 Germany+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 回答确认问题时,可以更改 Country 或 City .
当用户随后将 Country 从 France 更改为 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
进行确认并且不更改国家/地区并选择先前选择的县本身,则不会再次提示城市,直接确认选择 Country
和 City
被提示。
模拟器响应
我正在使用带有 FormFlow 的 Microsoft Bot Framework 让用户填写表单。 假设我的表单有两个字段:
- 国家
- 城市
所以我有两个枚举:
public enum Country {
France, Germany
}
public enum City {
Paris, Berlin
}
字段City总是依赖于字段Country,因为一个城市属于一个国家。 这意味着用户只能填写 France+Paris 或 Germany+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 回答确认问题时,可以更改 Country 或 City . 当用户随后将 Country 从 France 更改为 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
进行确认并且不更改国家/地区并选择先前选择的县本身,则不会再次提示城市,直接确认选择 Country
和 City
被提示。
模拟器响应