2013-04-01 42 views
2

我希望你的無限知識可以幫助我與這一個,我找不到任何類似的問題得到答案。Viewstate&動態創建UserControls - 第一次回發清除控制內容

概述如果代碼是TL; DR或反之亦然
我有一系列的用戶控件的,每一個是輸入表格提交時生成的電子郵件並在內部將其發送到任何相關位置。所有表格出現在同一頁面上,結構如下。

我有一個updatepanel - 在updatepanel內是多視圖,其中一個視圖包含所有電子郵件表單的用戶控件。 這個控件EmailForms.ascx實質上是一個1行2單元格的表格,在左邊的單元格中有一個樹形視圖,在右邊的單元格中有一個佔位符。樹視圖中每個葉子節點的值將子郵件表單用戶控件的URL保存在佔位符中。加載控件時,如果子電子郵件表單需要回發,則URL將以會話狀態存儲並在Page_Init中重新加載。

每個單獨的電子郵件表格都有自己的提交按鈕,0​​在Page_Init函數中調用。如果任何表單有其他元素需要回發,則以這種方式進行註冊。

的問題
一切幾乎完美的作品 - 我的問題是明確第一回發後,我改變顯示其子郵件的形式,當用戶填寫表單並點擊提交,所有的輸入地區清除後,所有驗證器都會顯示爲false,並且不會生成電子郵件。之後的每一次回發都會像以前一樣進行,直到再次將子電子郵件表單更改爲另一個。 要加載的第一封電子郵件表單不會遇到此問題。

任何人都可以提出什麼是造成這種行爲,我怎麼去防止它? 這是否可以嘗試提交以前加載的窗體的視圖狀態中的值?

Default.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> 

EmailForms.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> 

EmailForms.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 

回答

2

這是通過對創作&重裝每個控件分配一個ID解決,基於子控件的文件路徑。
如果不這樣做,我認爲無論加載哪個控件,自動生成的ID都是相同的,並且視圖狀態是第一次後續回發時的問題,因爲存儲的控件狀態與頁面上的控件不匹配。