我希望你无限的知识可以帮助我解决这个问题,我找不到任何类似的问题来得到答案。
概述如果代码是 tl;dr 或反之亦然
我有一系列用户控件,每个都是一个输入表单,提交时会生成一封电子邮件并将其在内部发送到任何相关位置。所有表格都出现在同一页面上,结构如下。
我有一个更新面板 - 在更新面板中有一个多视图,其中一个视图包含所有电子邮件表单的用户控件。这个控件,EmailForms.ascx - 本质上是一个 1 行,2 个单元格的表格,左侧单元格中有一个树视图,右侧单元格中有一个占位符。树视图中每个叶节点的值包含要加载到占位符中的子电子邮件表单用户控件的 URL。加载控件时,URL 存储在会话状态中,Page_Init
如果子电子邮件表单需要回发,则重新加载。
每个单独的电子邮件表单都有自己的提交按钮,并ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(btn_Submit)
在Page_Init
函数中调用。如果任何表单有其他需要引起回发的元素,它们就会以这种方式注册。
问题
一切都几乎完美运行 - 我的问题特别是在我更改显示哪个子电子邮件表单后的第一次回发,当用户填写表单并点击提交时,所有输入区域都被清除,所有验证器都显示为 false 和不生成电子邮件。每次后续回发都会正常工作,直到再次将子电子邮件表单更改为另一个表单。要加载的第一个电子邮件表单不会遇到此问题。
谁能建议导致这种行为的原因以及我如何防止它?这可能是在尝试提交先前加载的表单的视图状态中的值吗?
默认.aspx
<body>
<form id="MainForm" runat="server">
<asp:ScriptManager ID="NavigatorScriptManager" runat="server" EnablePartialRendering="true">
</asp:ScriptManager>
<!-- irrelevant stuff omitted -->
<asp:UpdatePanel ID="upd_Pan1" runat="server" >
<ContentTemplate>
<asp:MultiView ID="multi_MainRealContent" runat="server" ActiveViewIndex="0" >
<!-- Other views are fine -->
<asp:View runat="server" ID="View4">
<asp:Panel runat="server" ID="Panel5" CssClass="ViewContainer LeftAlignment">
<UsrCtrl:EmailForms ID="Sp_Emails" runat="server" width="95%" />
</asp:Panel>
</asp:View>
</asp:MultiView>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
电子邮件表单.ascx
<asp:Table runat="server" ID="tbl_ToolSelect" Width="100%" CellSpacing="0" CssClass="LayoutTable EmailFormsTable">
<asp:TableRow ID="TableRow1" runat="server">
<asp:TableCell ID="TableCell1" runat="server" Width="300px">
<asp:TreeView runat="server" ID="tree_EmailForms"
DataSourceID="xml_EmailForms"
ExpandDepth="0" ShowLines="false"
NodeIndent="10" NodeWrap="True" PopulateNodesFromClient="false"
ShowExpandCollapse="True" >
<DataBindings>
<asp:TreeNodeBinding DataMember="Pillar" TextField="id" SelectAction="None" PopulateOnDemand="False" />
<asp:TreeNodeBinding DataMember="Group" TextField="id" SelectAction="None" PopulateOnDemand="False" />
<asp:TreeNodeBinding DataMember="Form" TextField="id" ValueField="url" SelectAction="Select" PopulateOnDemand="False" />
</DataBindings>
</asp:TreeView>
</asp:TableCell>
<asp:TableCell ID="TableCell2" runat="server" >
<asp:PlaceHolder runat="server" ID="Ctrl_Placeholder"></asp:PlaceHolder>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
<asp:XmlDataSource ID="xml_EmailForms" runat="server" DataFile="EmailFormHeirarchy.xml" XPath="ROOT/*"></asp:XmlDataSource>
电子邮件表单.ascx.vb
Protected Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
If (Not Session Is Nothing) AndAlso (Not Session("LastControl") Is Nothing) Then 'ONLY if we have selected an email form previously
'reload the UserControl
Dim ctrl As UserControl = LoadControl(Session("LastControl"))
Ctrl_Placeholder.Controls.Add(ctrl)
End If
End Sub
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(tree_EmailForms)
Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "EmailFormsCSS", "<link href='EmailForms/EmailForms.css' rel='stylesheet' type='text/css' />")
End Sub
Protected Sub tree_EmailForms_SelectedNodeChanged(sender As Object, e As System.EventArgs) Handles tree_EmailForms.SelectedNodeChanged
Try
Ctrl_Placeholder.Controls.Clear()
Dim ctrl As UserControl = LoadControl(tree_EmailForms.SelectedNode.Value)
Ctrl_Placeholder.Controls.Add(ctrl)
Session("LastControl") = tree_EmailForms.SelectedNode.Value
Catch ex As System.Exception
//Occasional viewstate errors if there has been a long time between postbacks
SharedFunctions.LogError(Me.Page, ex.Message, ex.StackTrace)
End Try
End Sub
GenericChildEmailForm.ascx
<div class="descriptionArea">
<h2 class="centered">FORM HEADING</h2>
<p>FORM DESCRIPTION</p>
</div>
<div runat="server" id="inputArea" class="inputArea">
<asp:Table ID="inputTable" runat="server" CssClass="inputTable">
<asp:TableRow>
<asp:TableHeaderCell CssClass="LeftColumn">
<asp:Label runat="server" Text="FIELD HEADING"></asp:Label>
<asp:RequiredFieldValidator runat="server" ID="val_req_ID" ControlToValidate="ID" Display="Dynamic" EnableClientScript="true" ErrorMessage="MESSAGE"> *</asp:RequiredFieldValidator>
</asp:TableHeaderCell>
<asp:TableCell CssClass="RightColumn">
<asp:Textbox runat="server" id="ID" width="98%"></asp:textbox>
</asp:TableCell>
</asp:TableRow>
<!-- repeat the above table row as required -->
<asp:TableRow>
<asp:TableCell ID="cell_HR" ColumnSpan="2">
<div style="width:98%"><hr /></div>
</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell ID="cell_Submit" ColumnSpan="2">
<asp:Button runat="server" ID="btn_Submit" Text="Submit" Width="98%" Height="30px" CausesValidation="true" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</div>
<div runat="server" id="errorArea" class="errorArea">
<asp:ValidationSummary runat="server" ID="val_Sumamry" DisplayMode="BulletList" ShowMessageBox="true" ShowSummary="false" />
</div>
<div runat="server" id="outputArea" class="confirmationArea">
</div>
GenericChildEmailForm.ascx.vb
Protected Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(btn_Submit)
End Sub
Protected Sub btn_Submit_Click(sender As Object, e As System.EventArgs) Handles btn_Submit.Click
//this function iterates over the input table and extracts the value fields of whatever controls appear in the cells. <hr> and submit rows excluded.
Dim emailBody As String = SharedFunctions.PrepareEmailBody(inputTable, Me.Page)
SharedFunctions.Send_Email("toAddress", "fromAddress", "displayName", "subject", emailBody)
outputArea.InnerHtml = "<h3>Email Sent</h3><p>A copy for your notes...</p><hr />" & emailBody
LogUsage() //in local database
SharedFunctions.ClearForm(FindControl("inputArea"))
End Sub