Repeater中使用DateControl后无法在后台代码访问控件求助
我来帮你一步步排查和解决这个问题,你遇到的btndetails为空的情况,主要是因为自定义控件的事件定义、Repeater的控件树重建,以及事件绑定这几个环节可能有疏漏。
1. 先确保自定义DateControl正确暴露并触发OnChange事件
你的前台已经绑定了OnChange="txtDate_PostBack",但如果DateControl内部没有定义这个事件并触发它,后台是接收不到正确的sender的。打开DateControl.ascx.vb,添加以下代码:
' 定义自定义Change事件 Public Event Change As EventHandler ' 下拉框选中事件的处理方法,触发自定义事件 Protected Sub DDLActual_OnChange(sender As Object, e As EventArgs) Handles ddlDay.SelectedIndexChanged, ddlMonth.SelectedIndexChanged, ddlYear.SelectedIndexChanged ' 把当前DateControl实例作为sender传递出去 RaiseEvent Change(Me, e) End Sub
这里要注意,要给三个DropDownList的SelectedIndexChanged事件都绑定到DDLActual_OnChange方法(或者你原来的方法),然后通过RaiseEvent把当前控件实例作为sender触发自定义事件。
2. 修正Repeater中事件的绑定方式
因为Repeater是动态生成控件的,直接在前台写OnChange可能不如后台绑定可靠。建议在Repeater的ItemDataBound事件里手动绑定DateControl的Change事件:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound ' 只处理数据项 If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then ' 找到Repeater项里的DateControl Dim dateCtrl As DateControl = DirectCast(e.Item.FindControl("txtDate"), DateControl) ' 绑定自定义Change事件 AddHandler dateCtrl.Change, AddressOf txtDate_PostBack ' 如果需要设置初始值,在这里处理 dateCtrl.Visible = True ' 注意:如果一开始设为false,回发时控件可能不在树中,建议按需显示 End If End Sub
另外,要确保Repeater在回发时能正确重建控件树:在Page_Load里,即使是回发,也不要漏掉必要的绑定(如果你的Repeater数据是动态的,最好确保每次回发都能重新绑定,或者依赖ViewState保留控件状态)。
3. 修正事件处理方法的逻辑
你的原有代码里有语法错误(多余的End If),而且直接用FindControl访问控件内部元素不够规范,建议封装属性:
第一步:在DateControl里封装Literal的访问属性
打开DateControl.ascx.vb,添加:
' 封装内部Literal的文本属性,供外部访问 Public ReadOnly Property IsFormulaAppliedText As String Get Dim ltr As Literal = DirectCast(Me.FindControl("ltrIsFormulaApplied"), Literal) Return If(ltr IsNot Nothing, ltr.Text, String.Empty) End Get End Property
第二步:修改事件处理方法
Protected Sub txtDate_PostBack(ByVal sender As Object, ByVal e As System.EventArgs) ' 转换sender为DateControl Dim dateCtrl As DateControl = TryCast(sender, DateControl) If dateCtrl IsNot Nothing Then ' 通过封装的属性获取Literal的值,不用直接FindControl Dim formulaText As String = dateCtrl.IsFormulaAppliedText ' 这里写你的业务逻辑 End If End Sub
4. 检查UpdatePanel的影响
你的DateControl内部有UpdatePanel,要确保:
- UpdatePanel的
UpdateMode设置合理,如果是Conditional,需要确保触发事件时能正确更新 - 如果Repeater本身也在另一个UpdatePanel里,要确保两个UpdatePanel的触发规则不冲突
- 不要让DateControl一开始就设置
Visible="false",如果需要隐藏,建议用CSS的display:none代替,因为Visible="false"会让控件不渲染到页面,回发时控件树里没有这个控件,导致事件无法触发。
按照以上步骤调整后,应该就能正确获取到dateCtrl实例,访问内部控件的值了。
内容的提问来源于stack exchange,提问作者ChandaMAMA

