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

Repeater生成的ASP.NET DropDownList首次选择不触发OnSelectedIndexChanged

问题原因分析
  1. 动态修改控件ID导致回发时控件树不匹配
    你在ItemDataBound事件中动态修改了DropDownList的ID并设置ClientIDMode=Static,首次页面渲染后客户端的控件ID是_ddlFieldXXX。但首次回发时,如果Repeater仅在!IsPostBack时绑定数据源,ItemDataBound不会触发,服务器端重建的DropDownList仍使用原始IDddlRepeater,导致服务器无法将回发的表单数据与控件匹配,最终事件不触发、状态丢失。而第二次回发时,若Repeater重新绑定,控件ID被修改为匹配的_ddlFieldXXX,所以功能恢复正常。

  2. DataBind顺序错误覆盖SelectedValue
    代码中先设置SelectedValue再调用DataBind(),DataBind()会重置控件的选中状态,导致首次绑定的选中值被覆盖,这也会影响ViewState的正确存储。


解决方案

方案1:移除动态修改ID的逻辑,保留原始控件ID

不需要修改DropDownList的ID,通过自定义属性区分不同下拉框,这是最优方案:

  1. 修改ItemDataBound事件代码:
protected void rptTemplateFields_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        dynamic field = e.Item.DataItem;
        BugFieldName fieldName = field?.FieldName;
        string fieldContent = field?.FieldContent;

        var allowedValues = GenerateAllowedValues(fieldName);

        if (!fieldName.IsNullOrUnsetValue() && !allowedValues.IsNullOrEmpty())
        {
            var ddl = e.Item.FindControl("ddlRepeater") as DropDownList;
            // 添加自定义属性存储fieldName,替代动态修改ID
            ddl.Attributes.Add("data-fieldname", fieldName.ToString());
            // 移除ClientIDMode=Static,保持默认规则避免控件树不匹配

            // 调整顺序:先绑定数据源,再设置选中值
            ddl.DataSource = allowedValues;
            ddl.DataBind();
            // 确保空选项存在(因AppendDataBoundItems=true,原空选项会保留,可根据需求调整)
            if (!ddl.Items.Contains(new ListItem("", "")))
            {
                ddl.Items.Insert(0, new ListItem("", ""));
            }
            // 设置选中值
            if (allowedValues.Contains(fieldContent))
            {
                ddl.SelectedValue = fieldContent;
            }
            ddl.Visible = true;
        }
    }
}
  1. 修改SelectedIndexChanged事件,通过自定义属性获取标识:
protected void ddlRepeater_SelectedIndexChanged(object sender, EventArgs e)
{
    var ddlRepeater = sender as DropDownList;
    string fieldName = ddlRepeater.Attributes["data-fieldname"];
    var state = (string)ViewState[fieldName];

    if (state != ddlRepeater.SelectedValue)
    {
        ViewState[fieldName] = ddlRepeater.SelectedValue;
    }
}

方案2:确保Repeater在每次回发时都重新绑定(不推荐)

如果必须保留动态ID,需要确保Repeater在**每次页面加载(包括回发)**时都重新绑定数据源,让ItemDataBound触发以同步控件ID:

在Page_Load事件中添加:

protected void Page_Load(object sender, EventArgs e)
{
    // 不要加!IsPostBack判断,确保每次回发都绑定Repeater
    rptTemplateFields.DataSource = rptrDataSource;
    rptTemplateFields.DataBind();
}

同时必须调整DataBind顺序(先绑定再设置SelectedValue),但此方法会增加服务器负载,仅作为备选方案。

额外注意事项

  • 确保Repeater和DropDownList的ViewState处于启用状态(默认启用,无需额外设置)。
  • 若不需要保留初始空选项,可移除AppendDataBoundItems=true,避免重复添加空项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:43:19