此 XML 文件适用于本示例:
<?xml version="1.0"?>
<!-- Custom fields per tenant/form -->
<Customers>
<IBM>
<Employee>
<Field Id="FirstName" Label="First name" />
<Field Id="LastName" Label="Last name" />
</Employee>
</IBM>
</Customers>
首先在页面上配置一个 XmlDataSource。如果您计划将表单定义与客户一起存储在数据库中,而不是存储在 XML 文件中,则可以将其替换为 SqlDataSource。
<asp:XmlDataSource ID="CustomFields" runat="sever"
DataFile="~/App_Data/CustomFields.config"
XPath="//Customers/IBM/Employee">
</asp:XmlDataSource>
在这种情况下,我们将使用一个 XML 文件,每个客户都有一个节点,而每种类型的表单都有另一个节点。在此示例中,IBM 是客户,而 Employee 是表单。当然 XPath 属性需要动态设置:
protected void Page_Load()
{
if(!Page.IsPostBack)
{
CustomFields.XPath = String.Format("//Customers/{0}/{1}", CustomerName, FormName);
}
}
现在您可以使用 ListView 对表单的一部分进行数据绑定,使用 XML 中的属性为每个字段显示一个 TextBox 控件:
<asp:ListView ID="DynamicFields" runat="server"
DataSourceID="CustomFields"
ItemPlaceHolderID="Item">
<LayoutTemplate>
<fieldset>
<legend>Custom fields</legend>
<asp:PlaceHolder ID="Item" runat="server" />
</fieldset>
</LayoutTemplate>
<ItemTemplate>
<div>
<asp:Label runat="server"
Text='<%# XPath("Field/@Label") %>'
AssociatedControlID="Field" />
<br />
<asp:TextBox ID="Field" runat="server"
data-field-id='<%# XPath("Field/@Id") %>' />
</div>
</ItemTemplate>
</asp:ListView>
在您后面的代码中,您现在可以检索每个字段的值并使用 data-field-id 属性将它们映射回来:
protected void Save_Click(object sender, EventArgs e)
{
foreach(ListViewItem item in DynamicFields.Items)
{
TextBox field = item.FindControl("Field") as TextBox;
string id = field.Attributes["data-field-id"];
string value = field.Text;
}
}
当然,当您还想将数据加载到编辑表单的字段中时,它会变得更加复杂,但这只是基于您自己的建议的一般方法。
存储需要考虑的一些事情是映射到一个特殊的表,其中包含每种数据类型(字符串、数字、日期等)的列。为此,您需要使用数据类型对 XML 进行注释,并据此验证输入。
<Field Id="FirstName" Label="First Name" Type="String" />
<Field Id="DateOfBirth" Label="Date of birth" Type="DateTime" />
如果您不需要,那么您可以考虑将所有值序列化为单个字符串(JSON?),以便存储在数据库的单个列中。这使得几乎不可能对数据运行查询。
{ "FirstName": value, "LastName": value }