You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历DataTable并添加可回传数据的服务器端TextBox/TextArea

解决ASP.NET动态生成能回传数据的TextBox/TextArea问题

为啥之前的方法拿不到值

你直接拼接HTML生成的<textarea>是纯客户端控件,没有加runat="server"属性,ASP.NET不会将其纳入服务器控件生命周期管理,回传时自然无法获取到输入值。

方案一:动态添加服务器端控件(最靠谱)

别再靠拼接HTML字符串生成控件,直接在后台创建ASP.NET服务器控件实例,添加到页面的容器控件中,这样控件会被ASP.NET完整管理,回传时能稳定获取输入值。

步骤:

  1. 在ascx页面添加一个PlaceHolder作为动态控件的容器(必须是服务器控件):
<asp:PlaceHolder ID="phControls" runat="server"></asp:PlaceHolder>
  1. 后台代码遍历DataTable,创建控件并添加到容器:
protected void Page_Load(object sender, EventArgs e)
{
    Guid itemGUID = new Guid("你的目标ID");
    // 无论是否回传,都要重新创建控件,否则ASP.NET无法识别原有控件
    LoadDynamicControls(itemGUID);
}

private void LoadDynamicControls(Guid ItemGUID)
{
    DataTable dt = new DataTable();
    // 这里写你的数据获取逻辑,从数据库填充DataTable

    foreach (DataRow dr in dt.Rows)
    {
        // 创建包裹标题和输入框的div
        HtmlGenericControl div = new HtmlGenericControl("div");
        
        // 添加标题元素
        HtmlGenericControl h3 = new HtmlGenericControl("h3");
        h3.InnerText = dr["Name"].ToString();
        div.Controls.Add(h3);

        // 创建服务器端TextArea(用TextBox控件,设置TextMode为MultiLine)
        TextBox txtArea = new TextBox();
        txtArea.ID = "txt_" + dr["ItemGUID"].ToString(); // 设置唯一ID关联数据行
        txtArea.TextMode = TextBoxMode.MultiLine;
        txtArea.MaxLength = 1000;
        txtArea.Style["width"] = "90%";
        txtArea.Style["height"] = "150px";
        // 如有默认值,直接从DataRow中赋值
        txtArea.Text = dr["DefaultContent"]?.ToString() ?? "";
        
        div.Controls.Add(new LiteralControl("<br />"));
        div.Controls.Add(txtArea);
        div.Controls.Add(new LiteralControl("<br />"));

        // 将组装好的div添加到PlaceHolder
        phControls.Controls.Add(div);
    }
}
  1. 回传时获取输入值:
// 示例:提交按钮点击事件中获取所有输入值
protected void btnSubmit_Click(object sender, EventArgs e)
{
    foreach (Control ctrl in phControls.Controls)
    {
        if (ctrl is HtmlGenericControl div && div.HasControls())
        {
            foreach (Control childCtrl in div.Controls)
            {
                if (childCtrl is TextBox txt && txt.ID.StartsWith("txt_"))
                {
                    string inputValue = txt.Text;
                    string itemGUID = txt.ID.Replace("txt_", "");
                    // 这里处理获取到的值,比如存入数据库
                }
            }
        }
    }
}

划重点:动态创建的服务器控件必须在每次页面加载(包括回传)时重新创建,且ID要和第一次创建时完全一致,否则ASP.NET无法恢复控件状态和输入值。

方案二:临时快速解决方法

如果不想大幅修改现有代码,可以尝试以下两种方式,但稳定性和可维护性不如方案一。

方式1:给HTML控件加runat="server"

拼接HTML时给textarea加上runat="server",同时确保div_contents本身是服务器控件(带runat="server"属性):

content += "<br /><textarea runat=\"server\" ID=\"txt_" + dr["ItemGUID"].ToString() + 
           "\" MaxLength=\"1000\" style=\"width:90%; height:150px\"></textarea><br />";

后端通过FindControl获取控件值:

TextBox txt = div_contents.FindControl("txt_xxxx") as TextBox;
if (txt != null)
{
    string value = txt.Text;
}

缺点:回传时可能因控件树重建问题导致无法获取值,稳定性差。

方式2:通过Request.Form直接获取值

不给控件加runat="server",但添加name属性,回传时通过表单提交的键值对直接获取:

content += "<br /><textarea name=\"txt_" + dr["ItemGUID"].ToString() + 
           "\" MaxLength=\"1000\" style=\"width:90%; height:150px\"></textarea><br />";

后端取值:

string value = Request.Form["txt_xxxx"];

优点:实现简单,无需依赖服务器控件生命周期;缺点:无法利用ASP.NET的控件状态管理,默认值回显等逻辑需自行处理。

总结

优先选择方案一,虽然需要调整现有代码结构,但最稳定可靠,符合ASP.NET的开发规范。方案二适合临时快速解决小需求,但长期维护容易出现问题。

内容的提问来源于stack exchange,提问作者dwewers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:45:17