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

ASP.NET中按钮点击后保留动态创建DropDownList的选中值

问题分析与解决方案

你的核心问题在于ASP.NET动态控件的生命周期管理:动态创建的控件必须在每次页面回发时重新创建(且保持ID不变),否则ViewState无法恢复控件状态,SelectedIndexChanged事件也不会触发。结合你的场景,我整理了关键修复点和完整的修正代码:

关键问题拆解

  1. 动态控件必须每次回发重建:你修改后的代码在回发时尝试复用旧的DropDownList实例,这是错误的——ASP.NET页面回发时会重建整个控件树,旧实例已失效,必须重新创建并保持相同ID,ViewState才会自动恢复选中状态。
  2. 事件绑定时机:动态控件的事件绑定必须在每次创建控件时执行,不能仅在首次加载时绑定。
  3. 默认值初始化仅需首次加载:只有页面首次加载时,才需要设置默认选中值并初始化namesMapping,回发时依赖ViewState恢复状态即可。

修正后的完整代码

protected Dictionary<string, string> namesMapping;
protected PdfDocument doc;
protected PdfField[] fields;

protected void Page_Load(object sender, EventArgs e)
{
    // 1. 初始化全局对象(仅首次加载时执行)
    if (!IsPostBack)
    {
        doc = new PdfDocument(pdfFileName);
        fields = doc.Fields;
        namesMapping = new Dictionary<string, string>();
    }

    // 2. 每次回发都要重建动态控件(核心逻辑!)
    RecreateDynamicDropDowns();
}

private void RecreateDynamicDropDowns()
{
    // 清空现有行,避免重复创建控件
    Table1.Rows.Clear();

    ListItem[] listItems = new ListItem[4]
    {
        new ListItem("First Name", "first-name"),
        new ListItem("Last Name", "last-name"),
        new ListItem("Email", "email"),
        new ListItem("Company", "company")
    };

    foreach (PdfField field in fields)
    {
        if (field.GetType() == typeof(PdfTextField))
        {
            TableRow tr = new TableRow();
            
            // 添加字段名称单元格
            TableCell nameCell = new TableCell { Text = field.Name };
            tr.Cells.Add(nameCell);
            
            // 添加下拉列表单元格
            TableCell ddlCell = new TableCell();
            DropDownList dropdown = new DropDownList
            {
                ID = field.Name,
                AutoPostBack = true // 必须开启,才能触发SelectedIndexChanged事件
            };

            // 填充下拉选项(每次重建控件都要添加)
            dropdown.Items.AddRange(listItems);
            
            // 绑定选中变更事件(每次创建控件都要绑定)
            dropdown.SelectedIndexChanged += Dropdown_SelectedIndexChanged;
            
            ddlCell.Controls.Add(dropdown);
            tr.Cells.Add(ddlCell);
            
            Table1.Rows.Add(tr);

            // 首次加载时初始化默认映射值
            if (!IsPostBack)
            {
                namesMapping.Add(field.Name, dropdown.SelectedValue);
            }
            else
            {
                // 回发时同步当前选中值到映射字典
                namesMapping[field.Name] = dropdown.SelectedValue;
            }
        }
    }
}

private void Dropdown_SelectedIndexChanged(object sender, EventArgs e)
{
    DropDownList dropDown = (DropDownList)sender;
    // 实时更新映射字典的选中值
    namesMapping[dropDown.ID] = dropDown.SelectedValue;
}

// 示例按钮点击事件:获取所有下拉列表的选中值
protected void SubmitButton_Click(object sender, EventArgs e)
{
    // 遍历表格行获取每个下拉列表的选中状态
    foreach (TableRow row in Table1.Rows)
    {
        if (row.Cells.Count > 1)
        {
            DropDownList ddl = row.Cells[1].Controls[0] as DropDownList;
            if (ddl != null)
            {
                string fieldName = ddl.ID;
                string selectedValue = ddl.SelectedValue;
                // 这里可以直接使用namesMapping[fieldName],或者直接用selectedValue
            }
        }
    }
}

额外说明

  • AutoPostBack=true:这是触发SelectedIndexChanged事件的必要条件,必须为DropDownList设置。
  • ViewState的作用:只要每次回发都重建ID相同的控件,ASP.NET会自动通过ViewState恢复控件的选中状态,无需手动保存/恢复。
  • 获取选中值的方式:在按钮点击事件中,你可以直接遍历Table1中的控件,或者通过namesMapping字典获取(因为SelectedIndexChanged事件已经实时更新了它)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:52:52