2012-08-17 53 views
0

我有一個窗體,其值爲1-10的下拉列表的面板。當面板上的按鈕被按下時,該面板變得不可見,而另一面變得可見。在第二個面板上,我有一些動態生成的控件。行數由下拉列表中的selecteditem決定。在回發期間保留動態創建的控件 - VB.net

我的問題是,當我想要進行驗證,然後存儲動態創建的控件內容的值時,控件將被刪除。

我明白這是關於頁面的生命週期和動態創建的控件的持久性,但我不知道繞開這個問題。我已經閱讀了許多其他類似的問題,很少有人能夠解決這個問題的實例,所以我並不聰明。這包括建議動態創建的控件需要在頁面加載或pageinit上創建,這怎麼可能,因爲我們不知道要做多少?

任何幫助一如既往,非常感謝。

Imports DotNetNuke.Entities.Modules 
Imports DotNetNuke 
Imports System 
Imports System.Web.UI 
Imports System.Web.UI.WebControls 
Imports System.Collections.Generic 
Imports System.Reflection 
Imports System.Web.Configuration 
Imports System.Net.Mail 
Imports System.Data.SqlClient 

Partial Class View 
Inherits SeatPlannerModuleBase 
Implements IActionable 
Dim valid As String = "success" 

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load, Me.Load 
    Try 

     If Not Page.IsPostBack Then 

     End If 

    Catch exc As Exception  'Module failed to load 
     ProcessModuleLoadException(Me, exc) 
    End Try 
End Sub 

Public ReadOnly Property ModuleActions() As Entities.Modules.Actions.ModuleActionCollection Implements Entities.Modules.IActionable.ModuleActions 
    Get 
     Dim Actions As New Entities.Modules.Actions.ModuleActionCollection 
     Actions.Add(GetNextActionID, Localization.GetString(Entities.Modules.Actions.ModuleActionType.AddContent, LocalResourceFile), Entities.Modules.Actions.ModuleActionType.AddContent, "", "", EditUrl(), False, DotNetNuke.Security.SecurityAccessLevel.Edit, True, False) 
     Return Actions 
    End Get 
End Property 

Protected Sub Filldata() 
    Dim conn As New SqlConnection() 
    conn.ConnectionString = WebConfigurationManager.ConnectionStrings("Congress_SeatPlanner_ConnectionString").ConnectionString 
    Dim Qstr As String = "select * From [Seat_planner_2013].[dbo].[booking]" 
    Try 
     Using connection As New SqlConnection(conn.ConnectionString) 
      connection.Open() 
      Dim command As New SqlCommand(Qstr, connection) 
      Dim reader As SqlDataReader = command.ExecuteReader() 
      If reader.Read() Then 
       Try 
        Dim title As String 

        title = reader("title") 
        title = title.Trim 
        title_Txt.Text = title 
       Catch 
        title_Txt.Text = "" 
       End Try 
       Try 
        first_name_Txt.Text = reader("first_name") 
       Catch 
        first_name_Txt.Text = "" 
       End Try 
       Try 
        surname_Txt.Text = reader("surname") 
       Catch 
        surname_Txt.Text = "" 
       End Try 
       Try 
        company_name_Txt.Text = reader("company_name") 
       Catch 
        company_name_Txt.Text = "" 
       End Try 
       Try 
        contact_number_Txt.Text = reader("contact_phone") 
       Catch 
        contact_number_Txt.Text = "" 
       End Try 
       Try 
        contact_email_Txt.Text = reader("contact_email") 
       Catch 
        contact_email_Txt.Text = "" 
       End Try 
       Try 
        number_of_tickets_Ddl.SelectedValue = reader("number_of_tickets") 
       Catch 
        number_of_tickets_Ddl.SelectedValue = "" 
       End Try 
       Try 
        purchase_date_Txt.Text = reader("date_of_purchase") 
       Catch 
        purchase_date_Txt.Text = "" 
       End Try 
      End If 
     End Using 
    Catch ex As Exception 
     ErrLabel_Lbl.Visible = True 
     ErrLabel_Lbl.Text = ex.Message.ToString 
    End Try 
End Sub 

Protected Sub validate() 

    If title_Txt.Text.Length < 2 Then 
     title_error_Lbl.Text = "Please enter a title" 
     valid = "fail" 
    Else 
     title_error_Lbl.Text = "*" 
    End If 
    If first_name_Txt.Text.Length < 1 Then 
     first_name_error_Lbl.Text = "Please enter a first name" 
     valid = "fail" 
    Else 
     first_name_error_Lbl.Text = "*" 
    End If 
    If surname_Txt.Text.Length < 1 Then 
     surname_error_Lbl.Text = "Please enter a surname" 
     valid = "fail" 
    Else 
     surname_error_Lbl.Text = "*" 
    End If 
    If company_name_Txt.Text.Length < 1 Then 
     comnpany_name_error_Lbl.Text = "Please enter a company name" 
     valid = "fail" 
    Else 
     comnpany_name_error_Lbl.Text = "*" 
    End If 
    If contact_email_Txt.Text.Length < 1 Then 
     contact_email_error_Lbl.Text = "Please enter a contact email address" 
     valid = "fail" 
    Else 
     contact_email_error_Lbl.Text = "*" 
    End If 
    If contact_number_Txt.Text.Length < 1 Then 
     contact_phone_error_Lbl.Text = "Please enter a contact phone number" 
     valid = "fail" 
    Else 
     contact_phone_error_Lbl.Text = "*" 
    End If 
    If number_of_tickets_Ddl.SelectedValue = "Please select" Then 
     number_of_tickets_error_Lbl.Text = "Please select a number of tickets to allocate" 
     valid = "fail" 
    Else 
     number_of_tickets_error_Lbl.Text = "*" 
    End If 
    If purchase_date_Txt.Text.Length < 1 Then 
     date_of_purchase_error_Lbl.Text = "Please enter the date you purchased the tickets" 
     valid = "fail" 
    Else 
     date_of_purchase_error_Lbl.Text = "*" 
    End If 

    If valid = "fail" Then 
     ErrLabel_Lbl.Text = "Failed validation" 
    Else 
     ErrLabel_Lbl.Text = "Validation succeeded" 
    End If 

End Sub 

Protected Sub validate_step2() 

'validation here that doesn't work due to the postback issue 

End Sub 

Protected Sub IterateThroughTitle(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In title_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.TextBox") AndAlso c.ID Is Nothing Then 
      'DirectCast(c, TextBox).Text = "TextBox_Title " + count.ToString() 
      DirectCast(c, TextBox).ID = "TextBox_Title_" + count.ToString() 
      DirectCast(c, TextBox).CssClass = "DYN_TextBox" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughTitle(c) 
     End If 
    Next 
End Sub 

Protected Sub IterateThroughFirstname(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In firstname_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.TextBox") AndAlso c.ID Is Nothing Then 
      'DirectCast(c, TextBox).Text = "TextBox_Firstname " + count.ToString() 
      DirectCast(c, TextBox).ID = "TextBox_Firstname_" + count.ToString() 
      DirectCast(c, TextBox).CssClass = "DYN_TextBox" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughFirstname(c) 
     End If 
    Next 
End Sub 

Protected Sub IterateThroughSurname(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In surname_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.TextBox") AndAlso c.ID Is Nothing Then 
      'DirectCast(c, TextBox).Text = "TextBox_Surname " + count.ToString() 
      DirectCast(c, TextBox).ID = "TextBox_Surname_" + count.ToString() 
      DirectCast(c, TextBox).CssClass = "DYN_TextBox" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughSurname(c) 
     End If 
    Next 
End Sub 

Protected Sub IterateThroughTicketNum(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In ticketNum_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.TextBox") AndAlso c.ID Is Nothing Then 
      'DirectCast(c, TextBox).Text = "TextBox_TicketNum " + count.ToString() 
      DirectCast(c, TextBox).ID = "TextBox_TicketNum_" + count.ToString() 
      DirectCast(c, TextBox).CssClass = "DYN_TextBox" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughTicketNum(c) 
     End If 
    Next 
End Sub 

Protected Sub IterateThroughBooking(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In booking_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.Label") AndAlso c.ID Is Nothing Then 
      DirectCast(c, Label).Text = "Booking #" + count.ToString() 
      DirectCast(c, Label).ID = "BookLabel_" + count.ToString() 
      DirectCast(c, Label).CssClass = "DYN_Label" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughBooking(c) 
     End If 
    Next 
End Sub 

Protected Sub IterateThroughReservation(ByVal parent As Control) 
    Dim count As Integer = 1 

    For Each c As Control In res_Placeholder.Controls 
     If c.[GetType]().ToString().Equals("System.Web.UI.WebControls.Label") AndAlso c.ID Is Nothing Then 
      DirectCast(c, Label).Text = "Guest" 
      DirectCast(c, Label).ID = "ResLabel_" + count.ToString() 
      DirectCast(c, Label).CssClass = "DYN_Label" 
      count += 1 
     End If 

     If c.Controls.Count > 0 Then 
      IterateThroughReservation(c) 
     End If 
    Next 
End Sub 

Protected Sub Retreive_first_row() 

    CType(Me.FindControl("ResLabel_1"), Label).Text() = "You" 
    CType(Me.FindControl("TextBox_Title_1"), TextBox).Text() = title_Txt.Text 
    CType(Me.FindControl("TextBox_Title_1"), TextBox).Enabled() = False 
    CType(Me.FindControl("TextBox_Firstname_1"), TextBox).Text() = first_name_Txt.Text 
    CType(Me.FindControl("TextBox_Firstname_1"), TextBox).Enabled() = False 
    CType(Me.FindControl("TextBox_Surname_1"), TextBox).Text() = surname_Txt.Text 
    CType(Me.FindControl("TextBox_Surname_1"), TextBox).Enabled() = False 

End Sub 

Protected Sub CreateTextBoxes() 

    If Not Page.IsValid Then 
     Return 
    End If 

    Dim n As Integer = number_of_tickets_Ddl.SelectedValue 

    For i As Integer = 0 To n - 1 
     res_Placeholder.Controls.Add(New Label()) 
     booking_Placeholder.Controls.Add(New Label()) 

     title_Placeholder.Controls.Add(New TextBox()) 
     firstname_Placeholder.Controls.Add(New TextBox()) 
     surname_Placeholder.Controls.Add(New TextBox()) 
     ticketNum_Placeholder.Controls.Add(New TextBox()) 

    Next 

    IterateThroughBooking(Me) 
    IterateThroughReservation(Me) 
    IterateThroughTitle(Me) 
    IterateThroughFirstname(Me) 
    IterateThroughSurname(Me) 
    IterateThroughTicketNum(Me) 

    Retreive_first_row() 

End Sub 

Protected Sub testconn_submit_Btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles testconn_submit_Btn.Click 

    Filldata() 

End Sub 

Protected Sub next_submit_Btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles next_submit_Btn.Click 

    validate() 

    If valid = "fail" Then 

    Else 

     Step1_Pnl.Visible = False 
     Step2_Pnl.Visible = True 
     CreateTextBoxes() 
     Button1.Attributes.Add("OnClick", "validate_step2(); return false;") 
    End If 

End Sub 

Protected Sub clear_submit_Btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_submit_Btn.Click 

    title_Txt.Text = "" 
    first_name_Txt.Text = "" 
    surname_Txt.Text = "" 
    company_name_Txt.Text = "" 
    contact_number_Txt.Text = "" 
    contact_email_Txt.Text = "" 
    number_of_tickets_Ddl.SelectedValue = "Please select" 
    purchase_date_Txt.Text = "" 

    title_error_Lbl.Text = "*" 
    first_name_error_Lbl.Text = "*" 
    surname_error_Lbl.Text = "*" 
    comnpany_name_error_Lbl.Text = "*" 
    contact_phone_error_Lbl.Text = "*" 
    contact_email_error_Lbl.Text = "*" 
    number_of_tickets_error_Lbl.Text = "*" 
    date_of_purchase_error_Lbl.Text = "*" 

End Sub 

Protected Sub back_Btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles back_Btn.Click 

    Step1_Pnl.Visible = True 
    Step2_Pnl.Visible = False 

End Sub 

Protected Sub next_submit2_Btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles next_submit2_Btn.Click 

    validate_step2() 

End Sub 

End Class 
+0

您可以使用現有的隱藏控件來告訴您需要創建多少個動態控件。您也可以考慮更改用戶界面,以便您不必以此方式創建動態控件。 – Oded 2012-08-17 10:54:14

+0

我原本有一個非常簡單的10行控件網格,其中只有可見性發生了變化。這看起來非常麻煩,我認爲「動態」只能是更好。 – Ryan 2012-08-17 11:15:00

回答

0

第一次您的用戶選擇在下拉菜單中的項目下來,你得到的數量和創建動態控件。訣竅在於記住下一個PostBack的計數。

您可以使用會話來記住這個計數。

現在,當您收到第二個PostBack時,您可以重新創建Init上的控件。如果您希望這些動態創建的控件接收事件,Load爲時已晚。

+0

這是否會有效地「銷燬」控件,然後根據最初創建它們的數量重新創建新控件?如果這樣做是有道理的,但我怎麼也保留控件的價值? – Ryan 2012-08-17 11:22:18

+0

Http是無狀態的。控件始終在每個請求上創建。當它加載'ViewState'時,Asp.net填充值。如果您生成的第一次使用相同的ID,則asp.net將完成剩餘的ID。 – nunespascal 2012-08-17 11:24:20

+0

@Ryan - ViewState在Page_Init之後和Page_Load之前應用。您必須像以前一樣創建完全相同的控件,否則您將收到「ViewState無法應用」錯誤。 – 2012-08-17 11:26:25

1

通常,創建動態控件時,人們可能會在Page_Init創建控件並設置事件處理程序和所有的初始屬性(即ID,姓名,風格,文本等)。發生回發時,ViewState將在Page_Init之後應用(前提是啓用了ViewState)。

在這種情況下,我將更改爲中繼器或某種數據網格控件,並使用數據綁定來填充它。中繼器控件可以將數據綁定到基本數字數組中,重複您的模板X次。與中繼器這樣的

很好的例子可以在這裏找到:VB.NET Repeater Simple Data Binding Without Datasource

+0

看來我還是不太'相信'。如果我在Page_Init中生成控件的代碼基本上說 - 創建一個從1到DDL中的任何一個循環,然後創建許多行控件,這將在DDL被選中之前發生,它將如何「知道'要創建多少行? – Ryan 2012-08-17 11:09:00

+0

我看到你的問題...切換到中繼器控制 – 2012-08-17 11:20:04

+0

我根本沒有中繼器的經驗,你是否能夠闡明他們和他們的使用? – Ryan 2012-08-17 11:29:44

相關問題