嵌套DataList中DataList2_ItemCommand事件无法触发问题
三层嵌套DataList中DataList2_ItemCommand无法触发的问题修复
问题描述
使用3层嵌套的DataList控件,每层通过SQL查询加载数据。DataList1的ItemCommand事件可正常触发,页面加载时第一组数据显示正常,点击对应项能加载DataList2的数据;但DataList2的ItemCommand事件(CommandName为"Cladire")完全无法触发,无法加载DataList3的数据。
错误原因分析
- 控件ID冲突:嵌套DataList中的LinkButton设置了
ClientIDMode="Static",导致生成重复ID,破坏ASP.NET的事件路由机制。 - 事件处理逻辑错误:DataList2_ItemCommand中错误地在当前Item内查找DataList2控件,导致无法正确获取数据ID。
- 动态控件状态丢失:回发时未重新绑定DataList2,导致控件状态丢失,事件无法触发。
修复方案
1. 修正后端C#代码
protected void DataList1_ItemCommand(Object source, DataListCommandEventArgs e) { if (e.CommandName == "Obiectiv") { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { int idob = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex].ToString()); // 保存当前展开的IdOB到ViewState,用于回发时重新绑定 ViewState["ExpandedIdOB"] = idob; DataList firstDataList = e.Item.FindControl("DataList2") as DataList; List<SqlParameter> prm = new List<SqlParameter>(); prm.Add(new SqlParameter("@IdOB", idob)); firstDataList.DataSource = GetDataTable("SELECT DISTINCT IdCL,Cladire FROM tblCladire WHERE IdOB= @IdOB;", prm); firstDataList.DataBind(); HtmlControl theDivS = (HtmlControl)e.Item.FindControl("DivS"); theDivS.Attributes["class"] = theDivS.Attributes["class"].Replace("hidden", "").Trim(); } } } protected void DataList2_ItemCommand(Object source, DataListCommandEventArgs e) { if (e.CommandName == "Cladire") { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // 修正:直接从source获取当前DataList2实例,获取DataKey DataList currentDataList2 = source as DataList; int idcl = Convert.ToInt32(currentDataList2.DataKeys[e.Item.ItemIndex].ToString()); DataList thirdDataList = e.Item.FindControl("DataList3") as DataList; List<SqlParameter> prm = new List<SqlParameter> { new SqlParameter("@IdCL", idcl) }; thirdDataList.DataSource = GetDataTable("SELECT DISTINCT IdCA,Camera FROM tblCamera WHERE IdCL =@IdCL;", prm); thirdDataList.DataBind(); HtmlControl theDivT = (HtmlControl)e.Item.FindControl("DivT"); theDivT.Attributes["class"] = theDivT.Attributes["class"].Replace("hidden", "").Trim(); } } } // 页面回发时重新绑定已展开的DataList2 protected void Page_Load(object sender, EventArgs e) { if (IsPostBack && ViewState["ExpandedIdOB"] != null) { int idob = Convert.ToInt32(ViewState["ExpandedIdOB"]); // 找到对应的DataList1项,重新绑定DataList2 foreach (DataListItem item in DataList1.Items) { if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem) { int itemId = Convert.ToInt32(DataList1.DataKeys[item.ItemIndex]); if (itemId == idob) { DataList firstDataList = item.FindControl("DataList2") as DataList; List<SqlParameter> prm = new List<SqlParameter>(); prm.Add(new SqlParameter("@IdOB", idob)); firstDataList.DataSource = GetDataTable("SELECT DISTINCT IdCL,Cladire FROM tblCladire WHERE IdOB= @IdOB;", prm); firstDataList.DataBind(); HtmlControl theDivS = (HtmlControl)item.FindControl("DivS"); theDivS.Attributes["class"] = theDivS.Attributes["class"].Replace("hidden", "").Trim(); break; } } } } } private static DataTable GetDataTable(string query, IEnumerable<SqlParameter> prms = null) { string constr = ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString; using (SqlConnection conn = new SqlConnection(constr)) { using (SqlCommand cmd = new SqlCommand()) { cmd.CommandText = query; using (SqlDataAdapter sda = new SqlDataAdapter()) { cmd.Connection = conn; sda.SelectCommand = cmd; DataTable dt = new DataTable(); if (prms != null) { foreach (var prm in prms) { cmd.Parameters.Add(prm); } } sda.Fill(dt); return dt; } } } }
2. 修正前端ASPX代码
移除ClientIDMode="Static",并修正重复的LinkButton ID:
<div id="DivP" runat="server"> <div class="row no-gutters"> <asp:DataList ID="DataList1" runat="server" Style="width: 100%" OnItemCommand="DataList1_ItemCommand" DataKeyField="IdOB"> <ItemTemplate> <asp:TextBox ID="txtIDOB" class="hidden" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"IdOB")%>' /> <asp:LinkButton ID="LinkButton10" runat="server" Text='<%#Eval("Obiectiv")%>' CommandName="Obiectiv" UseSubmitBehavior="false" Style="font-size: 11px;background-color:lightgreen" class="form-control form-control-sm" /> <div id="DivS" runat="server" class="hidden"> <hr style="border: 1px solid #800080" /> <asp:DataList ID="DataList2" runat="server" Style="width: 100%" OnItemCommand="DataList2_ItemCommand" DataKeyField="IdCL"> <ItemTemplate> <asp:TextBox ID="txtIDCL" class="hidden" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"IdCL")%>' /> <asp:LinkButton ID="LinkButton11" runat="server" Text='<%#Eval("Cladire")%>' CommandName="Cladire" UseSubmitBehavior="false" Style="font-size: 11px;background-color:lightsalmon" class="form-control form-control-sm" /> <div id="DivT" runat="server" class="hidden"> <hr style="border: 1px solid #800080" /> <asp:DataList ID="DataList3" runat="server" Style="width: 100%" OnItemCommand="DataList3_ItemCommand" DataKeyField="IdCA"> <ItemTemplate> <asp:TextBox ID="txtIDCA" class="hidden" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"IdCA")%>' /> <!-- 修正重复ID,改为LinkButton12 --> <asp:LinkButton ID="LinkButton12" runat="server" Text='<%#Eval("Camera")%>' CommandName="Camera" UseSubmitBehavior="false" Style="font-size: 11px;background-color:lightblue" class="form-control form-control-sm" /> </ItemTemplate> </asp:DataList> <hr style="border: 1px solid #800080" /> </div> </ItemTemplate> </asp:DataList> <hr style="border: 1px solid #800080" /> </div> </ItemTemplate> </asp:DataList> </div> </div>
关键修复点总结
- 移除所有控件的
ClientIDMode="Static",确保ASP.NET生成唯一的客户端ID,保证事件路由正常。 - 修正DataList2_ItemCommand中的DataKey获取逻辑,直接通过事件源获取当前DataList实例。
- 在Page_Load中处理回发,重新绑定已展开的DataList2,维持控件状态和事件绑定。
内容的提问来源于stack exchange,提问作者NMV
相关产品推荐
相关产品推荐

