【问题标题】:What is best way to store controls and add controls dynamically to a existing form什么是存储控件并将控件动态添加到现有表单的最佳方法
【发布时间】:2023-03-15 17:53:01
【问题描述】:

我有一个显示默认控件的通用表单。我正在尝试构建一个表单队列,如果我们有一个需要额外数据的客户端,我想存储捕获每个客户端数据所需的 asp.net 控件,并将它们与默认表单一起动态加载。

是否有人知道或指导我使用架构/解决方案来实现这一点[存储表单并加载并将它们动态添加到现有表单并从中检索传递的数据]。

我最初的想法是为每个需要额外数据而不是现有静态表单数据的客户端使用 xml 文件,并根据文件名(与客户端名称匹配)加载此 xml,并将其添加到内容占位符,然后循环通过按钮单击页面以从这些动态字段中获取数据。

【问题讨论】:

  • 你的想法似乎还不错!

标签: c# asp.net user-controls custom-controls dynamic-data


【解决方案1】:

此 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 }

【讨论】:

  • 谢谢,这非常有用,如果我们想在 xml 中定义控件类型,我们可以这样做吗:文本框、带值的下拉列表、必填字段
  • 是的,但是您需要想出一个更可扩展的 XML 模式来定义字段。并且您应该将字段的呈现封装在健壮的用户或服务器控件中。一种接受定义并将其转换为控件、预填充值并添加验证器的方法。我想它看起来像&lt;my:CustomField ID="Field" runat="server" XmlDefinition='&lt;%# XPath("Field") %&gt;' /&gt;。可以检查这个控件是否有效以及值是什么:field.IsValidfield.Value
  • 谢谢!我注意到回发时列表视图中的所有控件都丢失了,不知道为什么。
【解决方案2】:

将所有控件添加到表单中。隐藏可选的并根据需要显示它们。

【讨论】:

  • 我想要这个动态,我想根据我添加到数据库的客户端动态加载控件,而不是每次我们有新客户端和新字段时重新编码表单和重新发布。更清楚地说,此表格可供 1000 多个不同的客户使用
【解决方案3】:

我建议使用绑定,动态创建用户控件并将子控件绑定到队列的数据(具有绑定源),并在回发后从绑定源获取数据并在队列中更新.

【讨论】:

    猜你喜欢
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 2019-02-14
    • 2010-09-22
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多