1

目前我正在做一个名为在线考试的项目。所有控件都是动态创建的。

我有一个网页,我想在其中显示学生的详细信息。我在表格中正确显示了这些详细信息。现在是时候编辑这些细节了。要编辑记录,我使用名为编辑的链接按钮。当用户单击该链接按钮时,该行中的数据将替换为新的文本框。到这里我还好。现在,当我在对文本框进行更改后单击保存更改按钮时。旧值不会被新值替换,旧值仍然存在。

在表格中创建文本框的代码如下:

Public Sub Edit_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        For x As Integer = 0 To EditList.Count - 1

            If sender.id.substring(4) = EditList(x).ID.Substring(4) Then

                Session("PreviousRollNo") = RollNoList(x).Text

                Dim txtName As New TextBox
                txtName.Text = NameList(x).Text
                NameList(x).Text = ""
                NameList(x).Parent.Controls.Add(txtName)
                txtList.Add(txtName)

                Dim txtCourse As New TextBox
                txtCourse.Text = CourseList(x).Text
                CourseList(x).Text = ""
                CourseList(x).Parent.Controls.Add(txtCourse)
                txtList.Add(txtCourse)

                Dim txtAdmissionDate As New TextBox
                txtAdmissionDate.Text = AdmissionList(x).Text
                AdmissionList(x).Text = ""
                AdmissionList(x).Parent.Controls.Add(txtAdmissionDate)
                txtList.Add(txtAdmissionDate)

                Dim btnSaveChanges As New Button
                btnSaveChanges.Text = "Save Changes"
                EditList(x).Text = ""
                EditList(x).Parent.Controls.Add(btnSaveChanges)
                AddHandler btnSaveChanges.Click, AddressOf btnSaveChanges_Click
                Session("EditButtonClicked") = True

                Dim btnCancel As New Button
                btnCancel.Text = "Cancel"
                DeleteList(x).Text = ""
                DeleteList(x).Parent.Controls.Add(btnCancel)
                AddHandler btnCancel.Click, AddressOf btnCancel_Click
                Session("CancelButtonClicked") = True

                txtName.Focus()

                Exit For

            End If

        Next

    End Sub

保存更改按钮的代码如下:

Public Sub btnSaveChanges_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        If txtList(0).Text = "" Then

            Dim trError As TableRow = New TableRow

            Dim tdError As TableCell = New TableCell
            tdError.ColumnSpan = 7

            Dim lblError As New Label
            lblError.Text = "Please enter name of the student."
            lblError.ForeColor = Drawing.Color.Red
            tdError.Controls.Add(lblError)

            trError.Controls.Add(tdError)

            tbl.Controls.Add(trError)

        ElseIf txtList(1).Text = "" Then

            Dim trError As TableRow = New TableRow

            Dim tdError As TableCell = New TableCell
            tdError.ColumnSpan = 7

            Dim lblError As New Label
            lblError.Text = "Please enter the course."
            lblError.ForeColor = Drawing.Color.Red
            tdError.Controls.Add(lblError)

            trError.Controls.Add(tdError)

            tbl.Controls.Add(trError)

        ElseIf txtList(2).Text = "" Then

            Dim trError As TableRow = New TableRow

            Dim tdError As TableCell = New TableCell
            tdError.ColumnSpan = 7

            Dim lblError As New Label
            lblError.Text = "Please enter the Admission Date"
            lblError.ForeColor = Drawing.Color.Red
            tdError.Controls.Add(lblError)

            trError.Controls.Add(tdError)

            tbl.Controls.Add(trError)

        Else

            Dim cb As New OleDbCommandBuilder(da)

            Dim editRow() As DataRow

            editRow = ds.Tables("Student_Detail").Select("Roll_No = '" & Session("PreviousRollNo") & "'")

            editRow(0)("Name") = txtList(0).Text
            editRow(0)("Course") = txtList(1).Text
            editRow(0)("Admission_Date") = txtList(2).Text

            da.Update(ds, "Student_Detail")

            Page.Response.Redirect("ChangeUserDetails.aspx")

        End If

    End Sub

我收到错误提示数组超出范围。在 btnSaveChanges_Click 的第一行。这意味着当我点击保存更改按钮时,txtlist 总是被清除。所以我将 txtList 存储在像 Session("txtList") = txtList 这样的 Session 中。并从中检索数据。但是现在我得到了文本框的旧值而不是新值。这里 txtList 是一个列表(文本框)

4

1 回答 1

3

首先,欢迎来到ASP.NET WebForms 页面生命周期。用简单的助记符记住它的模式:SILVER = Start、Init、Load、Validate、Events、Render。

其次,HTTP 是无状态的。WebForms使用 ViewState 对你隐藏这个事实做了一个了不起的工作,直到你做了一些不寻常的事情(正如你现在正在尝试的那样),这一切似乎都分崩离析了。真正发生的是,您开始看到WebForms管理方式的副作用,以及它WinForms与您想象的(或其他有状态系统)的不同之处。

当您在 中响应事件服务器端时WebForms,很容易给人一种没有任何改变的印象。整个页面与您“上次”离开时一样。所有控件都在那里,您可能以编程方式设置的值仍然设置。魔法。不是魔法。实际发生的是整个页面已被重新构建以响应该事件。它是如何重建的?通过您的页面定义(标记)、控制事件处理程序中采取的操作以及form客户端回发的数据的组合。

令人困惑?好的,让我们考虑一个例子。假设您有一个带有两个控件的页面。一个名为的文本框和一个以事件处理程序命名txtInput的按钮。当用户第一次请求页面时,这些控件的 HTML 来自您的标记(aspx 页面)并返回给客户端。接下来,用户设置一个值并单击提交按钮。然后,服务器会根据您的标记从头开始重新创建页面。在生命周期的早期阶段,控件仍具有其默认值。然后我们进入生命周期阶段,“如果当前请求是回发,则控件属性会加载从视图状态和控件状态恢复的信息。” 换句话说,当生命周期到达btnSubmitbtnSubmit_ClicktxtInputLoadInit,该控件是从标记创建的,但仍具有其默认值。然后Load阶段根据回发数据设置值。

想知道这如何适用于您的场景?您正在添加动态控件以响应控件事件。这样做有两个问题:

  1. 在页面生命周期中Init,基于从客户端发回的数据设置值为时已晚(回想一下SILVEREvent之后 Init)。
  2. 您的按钮单击事件处理程序仅运行一次,以响应用户单击按钮的回发。但请记住,在每次回发时,页面都会完全重新创建。因此,就服务器而言,动态控件不再存在!您会注意到,不仅在响应提交事件时控件不存在服务器端,而且在页面处理它之后,它们也不再存在于客户端。

那么答案是什么?好吧,我链接的页面的“生命周期事件”部分提供了一个线索。它声明该PreInit事件用于(除其他外)“创建或重新创建动态控件”。我们为什么要这样做PreInit?因此,页面生命周期中的早期事件足以让以后的事件正确处理它(例如设置从客户端回传的值)。

现在,我知道,您想添加基于用户单击按钮的控件。这怎么搭配?诀窍是您必须自己管理“状态”。嗯?国家?我的意思是MyDynamicControlsShouldBeShown=真/假。单击按钮时,创建控件以响应按钮单击事件处理程序是正确的操作(那里实际上没有任何选择)。但是您需要以某种方式存储该状态,以便在对页面的后续请求中知道是否应该在PreInit. 一种巧妙的选择是在Request.Form.Keys. 如果Keys集合中存在控件 ID,则用户正在回发控件的值,因此您应该重新创建它。


关于使用 Session 的旁注

希望基于上述内容,您已经意识到为什么将控件放入其中Session不起作用。但需要明确的是,您放入Session对象中的控件不再是存在的页面的一部分(请记住,页面会为每个请求完全重新创建。这些控件不再与Page事件挂钩,所以没有将它们的值填充在Page Init和之间Load。如果它确实有效,它仍然不是一个特别好的主意,因为Session不是每个请求。那么如果用户在多个选项卡中打开相同的页面会发生什么?奇怪的事情,就是这样。

于 2013-04-24T22:53:32.397 回答