ASP.NET嵌套用户控件中Repeater事件未触发问题排查求助
问题场景
存在ASPX页面及两个嵌套用户控件,结构为:ASPX页面引用MedlemsLista用户控件,该控件的Repeater内部嵌套MedlemRow用户控件。点击MedlemRow中rptMedlemmar行内的LinkButton时,showMedlemClick事件未被MedlemsLista捕获,事件链路中断。
ASPX页面代码
<div class="row"> <div class="col-9"><usr:Medlemslista runat="server" ID="usrMedlemsLista" /></div> <div class="col-3" style="border: 1px solid darkgray; background-color: white; padding: 0px; font-size: 12px; min-height: 700px;"> <usr:MedlemsData runat="server" ID="usrMedlemsdata" Visible="false" /> </div> </div>
MedlemsLista用户控件(前端)
<asp:Repeater runat="server" ID="rptFastigheter"> <HeaderTemplate /> <ItemTemplate> <asp:Label runat="server" ID="lblFastighet" Text='<%#DataBinder.Eval(Container.DataItem, "Fastighetsbeteckning")%>' Visible="false" /> <usr:MedlemsRow runat="server" ID="usrMedlemsRow" /> </ItemTemplate> <FooterTemplate /> </asp:Repeater>
MedlemsLista用户控件(后台VB.NET代码)
Public Event showMedlemClick2 As EventHandler Protected Sub rptFastigheter_ItemDataBound(S As Object, e As RepeaterItemEventArgs) Handles rptFastigheter.ItemDataBound If e.Item.ItemType = ListItemType.Item Then Dim control As MedlemRow = DirectCast(e.Item.FindControl("usrMedlemsRow"), MedlemRow) AddHandler control.showMedlemClick, AddressOf showMedlem2 End If End Sub Protected Sub showMedlem2(s As Object, e As CommandEventArgs) Dim _eventCommands As New CommandEventArgs("MedlemsID", e.CommandArgument) RaiseEvent showMedlemClick2(Me, _eventCommands) End Sub
MedlemRow用户控件(前端)
<asp:Repeater runat="server" ID="rptMedlemmar"> <HeaderTemplate><div class="row"></HeaderTemplate> <ItemTemplate> <div class="col-1"><asp:LinkButton runat="server" ID="lnkNr" Text='<%#DataBinder.Eval(Container.DataItem, "Nr")%>' CommandArgument='<%#DataBinder.Eval(Container.DataItem, "MedlemsID")%>' OnCommand="showMedlem" /></div> <div class="col-2"><asp:LinkButton runat="server" ID="LinkButton1" Text='<%#DataBinder.Eval(Container.DataItem, "Fastighetsbeteckning")%>' CommandArgument='<%#DataBinder.Eval(Container.DataItem, "MedlemsID")%>' OnCommand="showMedlem" /></div> <div class="col-3"><asp:LinkButton runat="server" ID="LinkButton2" Text='<%#DataBinder.Eval(Container.DataItem, "Namn")%>' CommandArgument='<%#DataBinder.Eval(Container.DataItem, "MedlemsID")%>' OnCommand="showMedlem" /></div> <div class="col-2"><asp:LinkButton runat="server" ID="LinkButton3" Text='<%#fixMobil(DataBinder.Eval(Container.DataItem, "Mobil"))%>' CommandArgument='<%#DataBinder.Eval(Container.DataItem, "MedlemsID")%>' OnCommand="showMedlem" /></div> <div class="col-3"><asp:LinkButton runat="server" ID="LinkButton4" Text='<%#DataBinder.Eval(Container.DataItem, "Epost")%>' CommandArgument='<%#DataBinder.Eval(Container.DataItem, "MedlemsID")%>' OnCommand="showMedlem" /></div> <div class="col-1"> </div> </ItemTemplate> <FooterTemplate></div></FooterTemplate> </asp:Repeater>
MedlemRow用户控件(后台VB.NET代码)
Public Event showMedlemClick As EventHandler Protected Sub showMedlem(s As Object, e As CommandEventArgs) Dim _eventCommands As New CommandEventArgs("MedlemsID", e.CommandArgument) RaiseEvent showMedlemClick(Me, _eventCommands) End Sub
排查与修复方案
1. 事件类型不匹配
MedlemRow中定义的showMedlemClick事件类型为EventHandler,但触发时传入的是CommandEventArgs,参数类型不匹配会导致事件无法正确传递。
修复:
修改MedlemRow的事件定义为泛型事件,确保参数类型一致:
' MedlemRow后台代码修改 Public Event showMedlemClick As EventHandler(Of CommandEventArgs) Protected Sub showMedlem(s As Object, e As CommandEventArgs) RaiseEvent showMedlemClick(Me, e) ' 直接传递原参数,无需重新创建 End Sub
同步更新MedlemsLista中的事件绑定与处理逻辑:
' MedlemsLista后台代码修改 Public Event showMedlemClick2 As EventHandler(Of CommandEventArgs) Protected Sub rptFastigheter_ItemDataBound(S As Object, e As RepeaterItemEventArgs) Handles rptFastigheter.ItemDataBound ' 补充AlternatingItem类型,避免遗漏交替行的控件 If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then Dim control As MedlemRow = DirectCast(e.Item.FindControl("usrMedlemsRow"), MedlemRow) AddHandler control.showMedlemClick, AddressOf showMedlem2 End If End Sub Protected Sub showMedlem2(s As Object, e As CommandEventArgs) RaiseEvent showMedlemClick2(Me, e) End Sub
2. 事件委托绑定时机问题
ASP.NET中动态控件的事件委托必须在页面生命周期早期(如Init阶段)重新绑定,若仅在ItemDataBound中绑定,回发时rptFastigheter未重新数据绑定的话,ItemDataBound不会触发,导致事件委托丢失。
修复:
移除rptFastigheter数据绑定逻辑外的If Not IsPostBack判断,确保每次页面回发时都重新绑定数据,保证子控件重建并绑定事件。
3. 控件查找范围遗漏
当前仅判断ListItemType.Item类型,会漏掉Repeater的交替行(ListItemType.AlternatingItem),导致这些行内的usrMedlemsRow控件未绑定事件。
修复:
在rptFastigheter_ItemDataBound中同时判断ListItemType.Item和ListItemType.AlternatingItem,覆盖所有数据行。
内容的提问来源于stack exchange,提问作者Claes A

