在我的表单确认对话框后自定义导航表单
Customizing the Navigation Form after my form's confirmation dialog
我在 FormBuilder
上定义了一个自定义 MessageDelegate
传递给 .Confirm(...)
。 (见屏幕截图。)
我的问题是我想自定义当用户在 Confirm
对话框中选择 "No" 时出现的导航菜单。我发现 this SO post 似乎在朝着正确的方向前进,但我想要更多的定制。我仍然希望显示按钮列表,但我希望能够指定哪些按钮 appear/don 不显示,以及每个按钮上的文本,而不是让 FormFlow 自动填充它。
例如:
在我的用例中,我有一个 HasMiddleName
字段,后跟一个 MiddleName
字段,只有在 HasMiddleName
字段收到 "Yes"回答。我希望导航仅显示 "Middle Name",类似于它显示 First/Last 的方式。如果用户选择中间名,我希望它重定向到表单的 HasMiddleName
部分。
另一个调整是我希望能够格式化出生日期以仅显示 MM/dd/yyyy
.
我尝试使用 Pattern language,但无法正常工作...我想要的可能吗?如果我手动创建对话框,我想展示如何将其与 FormFlow 的导航相关联?
导航步骤的自定义有点棘手,因此我想出了一个解决方案来解决这个问题。诀窍是确保 MiddleName
字段在导航步骤滚动时处于非活动状态,并将 HasMiddleName
字段伪装成 MiddleName
字段,以便单击它会带您到HasMiddleName
字段。
// We want our HasMiddleName field to be treated as the "Middle Name" field for navigation purposes
[Describe("Middle Name"), Prompt("Does the dependent have a middle name?"), Template(TemplateUsage.NavigationFormat, "{&}({MiddleName})", FieldCase = CaseNormalization.None)]
public bool HasMiddleName { get; set; }
// I'm showing you how to use the "Unspecified" template but for some reason it doesn't work in the navigation step.
// Also, be careful about giving two fields the same description. It works in this case because of the tricks we're using.
[Optional, Describe("Middle Name"), Prompt("Please enter middle name {||}"), Template(TemplateUsage.NoPreference, "None"), Template(TemplateUsage.Unspecified, "None")]
public string MiddleName { get; set; }
[Template(TemplateUsage.NavigationFormat, "{&}({:d})", FieldCase = CaseNormalization.None)]
public DateTime DateOfBirth { get; set; }
public static IForm<MyClass> BuildForm()
{
var builder = new FormBuilder<MyClass>()
.Field(new FieldReflector<MyClass>(nameof(HasMiddleName)).SetNext((value, state) =>
{
// This NextDelegate will execute after the user enters a value for HasMiddleName
bool didTheySayYes = (bool)value;
// If MiddleName is inactive it will be skipped over
state._isMiddleNameActive = didTheySayYes;
if (didTheySayYes)
{
// We need to explicitly navigate to the MiddleName field
// or else it will go back to the confirmation step
// if a middle name had already been entered
return new NextStep(new[] { nameof(MiddleName) });
}
else
{
// We want to clear the middle name in case one had been entered before
state.MiddleName = null;
// This will go to either the DateOfBirth field or the confirmation step
// since the MiddleName field will be inactive in this case
return new NextStep();
}
}))
.Field(new FieldReflector<MyClass>(nameof(MiddleName)).SetActive(state => state._isMiddleNameActive))
.Field(new FieldReflector<MyClass>(nameof(DateOfBirth)))
.Confirm(async state =>
{
// We're making sure MiddleName is inactive at the confirmation step
// so it won't be visible in the navigation step,
// but since we're not changing the MiddleName field
// it can still be retrieved from the form's result
state._isMiddleNameActive = false;
return new PromptAttribute("Ok. Is this correct? {||}");
});
return builder.Build();
}
// This private field isn't included in the form
private bool _isMiddleNameActive;
另一方面,如果您真的想控制导航步骤中显示的按钮,还有另一种途径可以探索。上面的代码应该能很好地为您服务,但我觉得我应该简单地提一下这个其他技巧,因为我写了一个 post 关于如何做到这一点。如果您制作自己的提示器,您可以检查 PromptAsync
委托中的字段名称是否等于 __navigation__
,然后相应地生成一条消息。请记住,您仍然必须使用第一个解决方案中的一些来确保单击 "Middle Name" 会将您带到 HasMiddleName
字段。
我在 FormBuilder
上定义了一个自定义 MessageDelegate
传递给 .Confirm(...)
。 (见屏幕截图。)
我的问题是我想自定义当用户在 Confirm
对话框中选择 "No" 时出现的导航菜单。我发现 this SO post 似乎在朝着正确的方向前进,但我想要更多的定制。我仍然希望显示按钮列表,但我希望能够指定哪些按钮 appear/don 不显示,以及每个按钮上的文本,而不是让 FormFlow 自动填充它。
例如:
在我的用例中,我有一个
HasMiddleName
字段,后跟一个MiddleName
字段,只有在HasMiddleName
字段收到 "Yes"回答。我希望导航仅显示 "Middle Name",类似于它显示 First/Last 的方式。如果用户选择中间名,我希望它重定向到表单的HasMiddleName
部分。另一个调整是我希望能够格式化出生日期以仅显示
MM/dd/yyyy
.
我尝试使用 Pattern language,但无法正常工作...我想要的可能吗?如果我手动创建对话框,我想展示如何将其与 FormFlow 的导航相关联?
导航步骤的自定义有点棘手,因此我想出了一个解决方案来解决这个问题。诀窍是确保 MiddleName
字段在导航步骤滚动时处于非活动状态,并将 HasMiddleName
字段伪装成 MiddleName
字段,以便单击它会带您到HasMiddleName
字段。
// We want our HasMiddleName field to be treated as the "Middle Name" field for navigation purposes
[Describe("Middle Name"), Prompt("Does the dependent have a middle name?"), Template(TemplateUsage.NavigationFormat, "{&}({MiddleName})", FieldCase = CaseNormalization.None)]
public bool HasMiddleName { get; set; }
// I'm showing you how to use the "Unspecified" template but for some reason it doesn't work in the navigation step.
// Also, be careful about giving two fields the same description. It works in this case because of the tricks we're using.
[Optional, Describe("Middle Name"), Prompt("Please enter middle name {||}"), Template(TemplateUsage.NoPreference, "None"), Template(TemplateUsage.Unspecified, "None")]
public string MiddleName { get; set; }
[Template(TemplateUsage.NavigationFormat, "{&}({:d})", FieldCase = CaseNormalization.None)]
public DateTime DateOfBirth { get; set; }
public static IForm<MyClass> BuildForm()
{
var builder = new FormBuilder<MyClass>()
.Field(new FieldReflector<MyClass>(nameof(HasMiddleName)).SetNext((value, state) =>
{
// This NextDelegate will execute after the user enters a value for HasMiddleName
bool didTheySayYes = (bool)value;
// If MiddleName is inactive it will be skipped over
state._isMiddleNameActive = didTheySayYes;
if (didTheySayYes)
{
// We need to explicitly navigate to the MiddleName field
// or else it will go back to the confirmation step
// if a middle name had already been entered
return new NextStep(new[] { nameof(MiddleName) });
}
else
{
// We want to clear the middle name in case one had been entered before
state.MiddleName = null;
// This will go to either the DateOfBirth field or the confirmation step
// since the MiddleName field will be inactive in this case
return new NextStep();
}
}))
.Field(new FieldReflector<MyClass>(nameof(MiddleName)).SetActive(state => state._isMiddleNameActive))
.Field(new FieldReflector<MyClass>(nameof(DateOfBirth)))
.Confirm(async state =>
{
// We're making sure MiddleName is inactive at the confirmation step
// so it won't be visible in the navigation step,
// but since we're not changing the MiddleName field
// it can still be retrieved from the form's result
state._isMiddleNameActive = false;
return new PromptAttribute("Ok. Is this correct? {||}");
});
return builder.Build();
}
// This private field isn't included in the form
private bool _isMiddleNameActive;
另一方面,如果您真的想控制导航步骤中显示的按钮,还有另一种途径可以探索。上面的代码应该能很好地为您服务,但我觉得我应该简单地提一下这个其他技巧,因为我写了一个 post 关于如何做到这一点。如果您制作自己的提示器,您可以检查 PromptAsync
委托中的字段名称是否等于 __navigation__
,然后相应地生成一条消息。请记住,您仍然必须使用第一个解决方案中的一些来确保单击 "Middle Name" 会将您带到 HasMiddleName
字段。