GridView内嵌动态项的DropDownList回发时SelectedIndexChanged不触发问题
问题根因
- GridView同时绑定了
DataSourceID声明式数据源和手动调用DataBind(),双重绑定导致控件状态加载混乱。 - DropDownList动态选项生成时机错误,且回发时重复清空选项,覆盖了ViewState加载的用户选中值,导致回发事件无法匹配触发。
- 手动添加ListItem后多余调用
DataBind(),扰乱控件状态。
修正步骤
1. 调整ASCX代码
删除GridView的DataSourceID属性,完全使用手动绑定控制数据加载:
<asp:GridView ID="MyGV" runat="server" AutoGenerateColumns="False" Width="100%" OnRowDataBound="MyGV_OnRowDataBound"> <Columns> <asp:TemplateField > <ItemTemplate> <asp:DropDownList runat="server" ID="SectionDD" AppendDataBoundItems="True" AutoPostBack="True" OnSelectedIndexChanged="SectionDD_OnSelectedIndexChanged" > </asp:DropDownList> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView>
2. 修正后置代码逻辑
protected void Page_Init(object sender,EventArgs e) { // 所有请求都在Page_Init阶段绑定GridView,保证控件树在ViewState加载前生成完成 MyGV.DataBind(); } protected void SectionDD_OnSelectedIndexChanged(object sender, EventArgs e) { // 此处可正常获取选中值执行业务逻辑 DropDownList sectionDd = sender as DropDownList; string selectedVal = sectionDd.SelectedValue; } protected void MyGV_OnRowDataBound(object sender, GridViewRowEventArgs e) { using (EntitiesModel dbContext = new EntitiesModel()) { // 从数据库获取二维数组array if (e.Row.RowType == DataControlRowType.DataRow) { DropDownList sectionDd = (DropDownList)e.Row.FindControl("SectionDD"); // 仅首次加载时生成选项,回发时不再重复生成覆盖状态 if(!Page.IsPostBack) { sectionDd.Items.Clear(); if (array.Length == 3) { if(array[0][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[0][0], array[0][1])); if(array[1][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[1][0], array[1][1])); if(array[2][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[2][0], array[2][1])); } else if (array.Length == 2) { if (array[0][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[0][0], array[0][1])); if (array[1][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[1][0], array[1][1])); } else if (array.Length == 1) { if (array[0][2].ToDecimal() > 0) sectionDd.Items.Add(new ListItem(array[0][0], array[0][1])); } } } } } private void SaveToDB() { // 保存数据到数据库逻辑 // 保存完成后需要刷新数据时再手动调用一次绑定即可 MyGV.DataBind(); }
关键逻辑说明
- Page_Init阶段绑定GridView是为了保证控件树结构在ViewState加载前和上一次渲染完全一致,ViewState才能正确把用户选中值加载到DropDownList,触发对应的选中变更事件。
- 回发时不再清空重新生成DropDownList选项,避免覆盖ViewState加载的用户操作状态,解决选中值自动恢复初始值的问题。
- 去掉DropDownList多余的DataBind调用,手动添加ListItem不需要执行该方法,避免扰乱控件状态。
内容的提问来源于stack exchange,提问作者Darren Wood
相关产品推荐
相关产品推荐

