UpdatePanel内Repeater按钮仅触发一次回发后消失问题求助
问题诊断与解决方案
核心问题分析
出现这个问题的核心原因集中在三点:
- UpdatePanel触发器覆盖不全:当前仅绑定了LIST1的触发器,LIST2的按钮回发未被纳入异步回发范围,导致第二次回发时控件状态丢失。
- 手动回发逻辑错误:直接调用
__doPostBack触发UpdatePanel回发,未关联有效服务器端事件,后台无法正确识别操作指令,导致数据源丢失。 - 数据源未持久化:后台添加新行后,未将更新后的数据源存入ViewState/Session,第二次回发时数据源重置为空,parentRepeater无数据绑定导致div消失。
分步解决方案
1. 修正UpdatePanel触发器配置
给UpdatePanel添加LIST2的异步回发触发器,确保LIST2的操作被纳入异步回发范围:
<asp:UpdatePanel runat="server" ID="updPanelTeste" UpdateMode="Conditional"> <Triggers> <asp:AsyncPostBackTrigger ControlID="rptProjetos" EventName="ItemCommand" /> <!-- 添加parentRepeater的ItemCommand触发器 --> <asp:AsyncPostBackTrigger ControlID="parentRepeater" EventName="ItemCommand" /> </Triggers> <ContentTemplate> <!-- 原有内容 --> <asp:Repeater runat="server" ID="parentRepeater" OnItemCommand="parentRepeater_ItemCommand"> <!-- 原有ItemTemplate内容 --> </asp:Repeater> </ContentTemplate> </asp:UpdatePanel>
2. 改用服务器端事件绑定替代手动JS回发
放弃手动__doPostBack,直接让LIST2按钮触发服务器端事件,保证状态正确传递:
<asp:Button runat="server" CssClass="buttonAcoes" Text="+" ID="btnAddLiderado" CommandName="AddRow" CommandArgument='<%# string.Format("{0}|{1}", Eval("IdProjeto"), Eval("IdAssociado")) %>' UseSubmitBehavior="false" />
后台parentRepeater_ItemCommand事件处理添加逻辑:
protected void parentRepeater_ItemCommand(object source, RepeaterCommandEventArgs e) { if (e.CommandName == "AddRow") { // 解析参数 string[] args = e.CommandArgument.ToString().Split('|'); int idProjeto = int.Parse(args[0]); int idAssociado = int.Parse(args[1]); // 从ViewState获取当前数据源 List<YourModel> dataList = ViewState["ParentRepeaterData"] as List<YourModel> ?? new List<YourModel>(); // 构造新行数据(根据业务逻辑赋值) YourModel newItem = new YourModel() { IdProjeto = idProjeto, IdAssociado = idAssociado, MarginLeftText = "", LeftBorder = "", LeftBorderLast = "" }; dataList.Add(newItem); // 持久化数据源并重新绑定 ViewState["ParentRepeaterData"] = dataList; parentRepeater.DataSource = dataList; parentRepeater.DataBind(); // 手动更新UpdatePanel updPanelTeste.Update(); } }
3. 确保LIST1点击后数据源存入ViewState
在btnGerenciarProjeto_Click方法中,绑定parentRepeater时将数据源存入ViewState:
protected void btnGerenciarProjeto_Click(object sender, EventArgs e) { Button btn = sender as Button; int idProjeto = int.Parse(btn.CommandArgument); // 获取初始数据(业务逻辑实现) List<YourModel> initialData = GetProjetoAssociados(idProjeto); // 持久化数据源并绑定 ViewState["ParentRepeaterData"] = initialData; parentRepeater.DataSource = initialData; parentRepeater.DataBind(); updPanelTeste.Update(); }
4. 若坚持原有JS逻辑的修正方案
如果必须保留原JS回发方式,需修正回发目标为有效控件事件:
function test(IdProjeto, IdAssociado) { const txtLider = document.getElementById('<%=txtLiderDummy.ClientID%>'); const txtDummy = document.getElementById('<%=txtDummy.ClientID%>'); txtLider.value = IdAssociado; txtDummy.value = IdProjeto; // 触发txtDummy的TextChanged事件而非直接回发UpdatePanel __doPostBack(txtDummy.uniqueID, ''); }
后台在txtDummy_TextChanged事件中执行添加逻辑,同时保证数据源存入ViewState并重新绑定parentRepeater。
关键注意事项
- 必须将parentRepeater的数据源持久化到ViewState/Session,否则回发会重置数据。
- UpdatePanel设为
Conditional时,需手动调用updPanelTeste.Update()触发更新。 - 尽量统一使用服务器端事件绑定,避免混合手动回发导致的状态丢失问题。
内容的提问来源于stack exchange,提问作者Andymakeer ll
相关产品推荐
相关产品推荐

