Update Panel内DropDownList的SelectedIndexChanged事件无法触发问题
ASP.NET 3.5 DetailsView中DropDownList SelectedIndexChanged事件不触发问题
我正在使用ASP.NET 3.5(Visual Studio 2008,VB)开发项目,在DetailsView控件中借助UpdatePanel实现多控件的显隐交互逻辑:
- 单选按钮rblAttemptType有“Phone Call”和“Letter”两个选项,选择“Phone Call”时,显示通话时间文本框并启用单选按钮rblSuccess;选择“Letter”时隐藏该文本框并禁用rblSuccess,同时将其选中项设为“N/A”。
- 单选按钮rblSuccess有“N/A”“No”“Yes”三个选项,选择“No”时显示下拉列表ddlrncType,该下拉列表包含“no answer”“left voicemail”“Other”等选项,选择“Other”时需显示用于填写详情的文本框txrncOther。
目前前两步的SelectedIndexChanged事件均正常触发,但ddlrncType已设置AutoPostBack="True",其绑定的SelectedIndexChanged事件却始终无法触发。我尝试新增一个仅包含该下拉列表和txrncOther的UpdatePanel,并将ddlrncType设为异步回发触发器,问题仍未解决。
相关代码片段
ASPX页面代码
<asp:DetailsView ID="dvAppointment" runat="server" AutoGenerateRows="False" DataKeyNames="aID" Visible="False" Caption="Appointment Details" BorderColor="#189AA1" BorderStyle="Solid" BorderWidth="1px"> <RowStyle BackColor="White" BorderStyle="None" Font-Names="Verdana,Arial,Helvetica" Font-Size="11px" Font-Strikeout="False" /> <FieldHeaderStyle BackColor="#449c77" CssClass="white" Font-Bold="True" Width="15%" BorderColor="#189AA1" BorderStyle="Solid" BorderWidth="1px" /> <Fields> <asp:BoundField DataField="aID" HeaderText="aID" Visible="False" ReadOnly="True" /> <asp:TemplateField HeaderText="Attempt Type" SortExpression="AttemptType" HeaderStyle-VerticalAlign="Middle"> <ItemTemplate> <asp:Label ID="lblAttemptType" runat="server" Text='<%# Eval("AttemptTypeDetails") %>'></asp:Label> <br /> <asp:Label ID="lblAttemptMessage" runat="server" Text='<%# ContactAttemptMessage()%>' HtmlEncode="False" CssClass="FireBrick9" HtmlEncodeFormatString="False" /> </ItemTemplate> <InsertItemTemplate> <asp:Label ID="lblAttemptMessage" runat="server" Text='<%# ContactAttemptMessage()%>' HtmlEncode="False" CssClass="FireBrick9" HtmlEncodeFormatString="False" /> <asp:RadioButtonList ID="rblAttemptType" runat="server" RepeatDirection="Horizontal" AutoPostBack="true" OnSelectedIndexChanged="rblAttemptTypeChanged" CssClass="Text9B"> <asp:ListItem Value="1">Phone call</asp:ListItem> <asp:ListItem Value="2">Letter</asp:ListItem> </asp:RadioButtonList> </InsertItemTemplate> <HeaderStyle VerticalAlign="Middle"></HeaderStyle> </asp:TemplateField> <asp:TemplateField HeaderText="Attempt Date" SortExpression="AttemptDate"> <ItemTemplate> <asp:Label ID="lblAttemptDateWithTime" runat="server" Text='<%# AttemptDateDetails() %>'></asp:Label> </ItemTemplate> <InsertItemTemplate> <asp:TextBox ID="txAttemptDate" runat="server" AutoCompleteType="Disabled" AutoPostBack="False"></asp:TextBox> <asp:CalendarExtender ID="CalendarExtenderAttemptDate" runat="server" TodaysDateFormat="mm/dd/yyyy" TargetControlID="txAttemptDate"> </asp:CalendarExtender> <asp:UpdatePanel ID="UpdatePanelforAttempt" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="AttemptTimeLabel" runat="server" Text="Time of phone attempt (hh:mm AM/PM): " Visible="False"></asp:Label> <asp:TextBox ID="txAttemptTime" runat="server" ToolTip="Time should be in format XX:XX AM/PM" Visible="False"></asp:TextBox> <asp:MaskedEditExtender ID="txAttemptTimeTime_MaskedEditExtender" runat="server" CultureAMPMPlaceholder="" CultureCurrencySymbolPlaceholder="" CultureDateFormat="" CultureDatePlaceholder="" CultureDecimalPlaceholder="" CultureThousandsPlaceholder="" CultureTimePlaceholder="" Enabled="True" TargetControlID="txAttemptTime" Mask="99:99 LL" ClearMaskOnLostFocus="False" MaskType="Number"> </asp:MaskedEditExtender> <asp:Label ID="LabelSuccess" runat="server" Text="<br /><br />Was the attempt successful?" CssClass="Text8B" ></asp:Label> <asp:RadioButtonList ID="rblSuccess" runat="server" OnSelectedIndexChanged="rblSuccessChanged" RepeatDirection="Horizontal" AutoPostBack="True" Enabled='<%# IIF(Eval("AttemptType")=1,"true","false") %>'> <asp:ListItem Value="2">Yes</asp:ListItem> <asp:ListItem Value="1">No</asp:ListItem> <asp:ListItem Value="0" Selected="True">N/A</asp:ListItem> </asp:RadioButtonList> <asp:Label ID="lblNoContactReason" runat="server" Text="<br />Please clarify the contact attempt result:" Visible="False" CssClass="smTextItalic"></asp:Label> <asp:DropDownList ID="ddlrncType" runat="server" DataSourceID="sdsrncTypes" DataValueField="rncTypeID" DataTextField="rncType" Visible="false" AutoPostBack="True" OnSelectedIndexChanged="ddlrncTypeChanged"> </asp:DropDownList> <asp:Label ID="lblSpecify" runat="server" Text="<br /><br />Please Explain:<br />" CssClass="smTextbold" Visible="False"></asp:Label> <asp:TextBox ID="txrncOther" runat="server" Visible="false" ToolTip="Specific result (350 characters allowed)" TextMode="MultiLine" CssClass="MultiLineInsert" Width="35%" /> </ContentTemplate> </asp:UpdatePanel> </InsertItemTemplate> </asp:TemplateField> </Fields> <HeaderStyle BackColor="#449C77" BorderColor="#189AA1" BorderStyle="Solid" BorderWidth="1px" /> <InsertRowStyle Width="80%" BackColor="White" Font-Names="Verdana,Ariel,Helvetica" Font-Size="11px" /> <EditRowStyle Width="77%" BackColor="White" Font-Names="Verdana,Ariel,Helvetica" Font-Size="11px" /> <AlternatingRowStyle BackColor="#CFCFCF" Font-Names="Verdana,Ariel,Helvetica" Font-Size="11px" /> </asp:DetailsView>
VB后台代码
Protected Sub rblAttemptTypeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Dim iAttemptTimeLabel As Label = DirectCast(dvAppointment.FindControl("AttemptTimeLabel"), Label) Dim itxAttemptTime As TextBox = DirectCast(dvAppointment.FindControl("txAttemptTime"), TextBox) Dim irblSuccess As RadioButtonList = DirectCast(dvAppointment.FindControl("rblSuccess"), RadioButtonList) Dim iUpdatePanelforAttempt As UpdatePanel = DirectCast(dvAppointment.FindControl("UpdatePanelforAttempt"), UpdatePanel) Dim AttemptType As Integer = 0 If Not sender.selectedValue = String.Empty Then AttemptType = CInt(sender.selectedValue) ViewState("AttemptType") = CInt(sender.selectedValue) If AttemptType = 1 Then 'Phone If Not iAttemptTimeLabel Is Nothing Then iAttemptTimeLabel.Visible = True End If If Not itxAttemptTime Is Nothing Then itxAttemptTime.Visible = True End If If Not irblSuccess Is Nothing Then irblSuccess.Enabled = True irblSuccess.ClearSelection() End If ElseIf AttemptType = 2 Then 'Letter If Not iAttemptTimeLabel Is Nothing Then iAttemptTimeLabel.Visible = False End If If Not itxAttemptTime Is Nothing Then itxAttemptTime.Visible = False End If If Not irblSuccess Is Nothing Then irblSuccess.Enabled = False irblSuccess.SelectedIndex = 2 End If End If If Not iUpdatePanelforAttempt Is Nothing Then iUpdatePanelforAttempt.Update() End If End If End Sub Protected Sub rblSuccessChanged(ByVal sender As Object, ByVal e As System.EventArgs) Dim iddlrncType As DropDownList = DirectCast(dvAppointment.FindControl("ddlrncType"), DropDownList) Dim itxrncOther As TextBox = DirectCast(dvAppointment.FindControl("txrncOther"), TextBox) Dim ilblNoContactReason As Label = DirectCast(dvAppointment.FindControl("lblNoContactReason"), Label) Dim iUpdatePanelforAttempt As UpdatePanel = DirectCast(dvAppointment.FindControl("UpdatePanelforAttempt"), UpdatePanel) Dim Success as Integer = -1 If Not sender.selectedValue = String.Empty Then Success = CInt(sender.selectedValue) If Success = 1 Then If Not iddlrncType Is Nothing Then iddlrncType.Visible = True End If If Not ilblNoContactReason Is Nothing Then ilblNoContactReason.Visible = True End If Else If Not iddlrncType Is Nothing Then iddlrncType.Visible = False End If If Not ilblNoContactReason Is Nothing Then ilblNoContactReason.Visible = False End If End If If Not iUpdatePanelforAttempt Is Nothing Then iUpdatePanelforAttempt.Update() End If End If End Sub Protected Sub ddlrncTypeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Dim ilblSpecify As Label = CType(dvAppointment.FindControl("lblSpecify"), Label) Dim itxrncOther As TextBox = CType(dvAppointment.FindControl("txrncOther"), TextBox) Dim iUpdatePanelforAttempt As UpdatePanel = DirectCast(dvAppointment.FindControl("UpdatePanelforAttempt"), UpdatePanel) Dim rncTypeID as Integer = 0 If Not sender.selectedValue = String.Empty AndAlso IsNumeric(sender.selectedvalue) Then rncTypeID = CInt(sender.selectedValue) If rncTypeID = 5 Then If Not itxrncOther Is Nothing Then itxrncOther.Visible = True itxrncOther.Focus() If Not ilblSpecify Is Nothing Then ilblSpecify.Visible = True End If End If Else If Not itxrncOther Is Nothing Then itxrncOther.Visible = False If Not ilblSpecify Is Nothing Then ilblSpecify.Visible = False End If End If End If If Not iUpdatePanelforAttempt Is Nothing Then iUpdatePanelforAttempt.Update() End If End If End Sub
解决方案
1. 修正控件查找逻辑
DetailsView处于Insert模式时,模板内的控件不能直接通过dvAppointment.FindControl获取,需要先定位到Insert行再查找控件。修改所有事件中的控件查找代码,以rblSuccessChanged为例:
Protected Sub rblSuccessChanged(ByVal sender As Object, ByVal e As System.EventArgs) ' 获取Insert模式下的行 Dim insertRow As DetailsViewRow = dvAppointment.Rows(dvAppointment.Rows.Count - 1) Dim iddlrncType As DropDownList = DirectCast(insertRow.FindControl("ddlrncType"), DropDownList) Dim itxrncOther As TextBox = DirectCast(insertRow.FindControl("txrncOther"), TextBox) Dim ilblNoContactReason As Label = DirectCast(insertRow.FindControl("lblNoContactReason"), Label) Dim iUpdatePanelforAttempt As UpdatePanel = DirectCast(insertRow.FindControl("UpdatePanelforAttempt"), UpdatePanel) ' 剩余逻辑保持不变 End Sub
同理,rblAttemptTypeChanged和ddlrncTypeChanged事件中的控件查找都需要做相同修改。
2. 配置UpdatePanel触发器
在UpdatePanel中显式添加所有需要触发异步回发的控件触发器,确保事件能被正确捕获:
<asp:UpdatePanel ID="UpdatePanelforAttempt" runat="server" UpdateMode="Conditional"> <ContentTemplate> <!-- 原有内容 --> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="rblAttemptType" EventName="SelectedIndexChanged" /> <asp:AsyncPostBackTrigger ControlID="rblSuccess" EventName="SelectedIndexChanged" /> <asp:AsyncPostBackTrigger ControlID="ddlrncType" EventName="SelectedIndexChanged" /> </Triggers> </asp:UpdatePanel>
如果模板内控件ID无法被触发器识别,可以在后台代码的Page_Load事件中动态添加触发器:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not IsPostBack Then Dim updatePanel As UpdatePanel = DirectCast(dvAppointment.Rows(dvAppointment.Rows.Count - 1).FindControl("UpdatePanelforAttempt"), UpdatePanel) Dim ddl As DropDownList = DirectCast(dvAppointment.Rows(dvAppointment.Rows.Count - 1).FindControl("ddlrncType"), DropDownList) updatePanel.Triggers.Add(New AsyncPostBackTrigger() With {.ControlID = ddl.UniqueID, .EventName = "SelectedIndexChanged"}) End If End Sub
3. 确保控件状态正确
在显示ddlrncType时,确保控件的Enabled属性为True,并且如果是首次显示,重新绑定数据源(如果依赖动态数据源):
If Success = 1 Then If Not iddlrncType Is Nothing Then iddlrncType.Visible = True iddlrncType.Enabled = True ' 若数据源未提前绑定,添加此行 ' iddlrncType.DataBind() End If ' 剩余逻辑保持不变 End If
4. 检查ViewState设置
确保UpdatePanel和ddlrncType的EnableViewState属性为True,避免异步回发时控件状态丢失:
<asp:UpdatePanel ID="UpdatePanelforAttempt" runat="server" UpdateMode="Conditional" EnableViewState="True"> <!-- 内容 --> </asp:UpdatePanel> <asp:DropDownList ID="ddlrncType" runat="server" EnableViewState="True" ...> </asp:DropDownList>
内容的提问来源于stack exchange,提问作者Dave Starns
相关产品推荐
相关产品推荐

