救命!获得动态控制单选按钮的价值!

时间:2022-12-05 11:44:25

I am looking into create a dynamic survey as posted in Get User Input From Dynamic Controls but with some different environment.

我正在研究创建一个动态调查,发布在动态控件的获取用户输入中,但具有一些不同的环境。

Below is what i am trying to do:

以下是我想要做的事情:

First when the user click the button, it will populate a dynamic table with radio button for the survey questionnaire inside a placeholder. However, I was unable to get its value (for score calculation) after clicking the submit button. All the dynamic controls was gone. Beside i am using an ajax extension (updatePanel) for the development and I have been look into viewstate but I have no idea with it.

首先,当用户单击该按钮时,它将使用占位符内的调查问卷的单选按钮填充动态表。但是,单击提交按钮后,我无法获得其值(用于计算分数)。所有的动态控制都消失了。除了我正在使用ajax扩展(updatePanel)进行开发,我一直在查看viewstate,但我不知道它。

Does anyone have any ideas?

有没有人有任何想法?

Here i included some of my code:

这里我包含了一些代码:


Page

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:Button ID="btnTest" runat="server" Text="Take Test" OnClick="btnTest_Click" Visible="False" />
            <asp:Label ID="lblTestErrMsg" runat="server" 

ForeColor="Red"></asp:Label><br />
                <table id="tblTest" runat="server" style="width: 100%">
                    <tr>
                        <td>
                         <asp:PlaceHolder ID="phQuestionnaire" runat="server"></asp:PlaceHolder>
                            <br />
                            </td>
                    </tr>
                    <tr>
                        <td>
                            </td>
                    </tr>
                    <tr>
                        <td>
                            <asp:Label ID="lblResult" runat="server"></asp:Label></td>
                    </tr>
                    <tr>
                        <td>
                        </td>
                    </tr>
                </table>
            </ContentTemplate>
        </asp:UpdatePanel>

Create Dynamic Table function

创建动态表功能

*v_dtTable and v_dtTable2 contains the data from database

* v_dtTable和v_dtTable2包含来自数据库的数据

     Private Sub CreateDynamicTable(ByVal v_dtTable As Data.DataTable, ByVal v_dtTable2 As Data.DataTable)
    Me.phQuestionnaire.Controls.Clear()
    Dim cols As Integer = v_dtTable.Rows.Count + 2
    Dim rows As Integer = v_dtTable2.Rows.Count + 1
    Dim mid As Integer = v_dtTable.Rows.Count / 2

    Dim tbl As Table = New Table()
    tbl.ID = "tblQs"
    tbl.BorderWidth = 1
    tbl.CellPadding = 0
    tbl.CellSpacing = 0
    tbl.Width = 500
    tbl.EnableViewState = True

    Me.phQuestionnaire.Controls.Add(tbl)
    For i As Integer = 0 To rows - 1
        Dim tr As TableRow = New TableRow()
        Dim rowCnt As Integer = 1
        Dim colCnt As Integer = 0

        For j As Integer = 0 To cols - 1
            Dim tc As TableCell = New TableCell()
            tc.BorderWidth = 1
            Dim lbl As Label = New Label()
            Dim bol As Boolean = False

            If i = 0 Then       
                If j = 0 Then
                    tc.Text = "No."

                ElseIf j = 1 Then
                    tc.Text = "Question"

                Else
                    tc.Text = v_dtTable.Rows(j - 2).Item("scoreName")
                    tc.HorizontalAlign = HorizontalAlign.Center
                End If
                tc.BackColor = Drawing.Color.DeepSkyBlue
                tc.ForeColor = Drawing.Color.White
            Else
                If v_dtTable2.Rows(i - 1).Item("isHeader") Then
                    bol = True
                    tc.Text = v_dtTable2.Rows(i - 1).Item("TestQuestion")
                    tc.Style("font-weight") = "bold"

                ElseIf j = 0 Then
                    tc.Text = rowCnt
                    rowCnt += 1

                ElseIf j = 1 Then
                    tc.Text = v_dtTable2.Rows(i - 1).Item("TestQuestion")

                Else
                    Dim rBtn As RadioButton = New RadioButton
                    rBtn.GroupName = "rBtn" & rowCnt
                    rBtn.ID = "rBtn_" & rowCnt & "_" & colCnt
                    rBtn.InputAttributes("value") = v_dtTable.Rows(j - 2).Item("scoreValue")
                    colCnt += 1
                    If j = mid + 2 Then
                        rBtn.Checked = True
                    End If

                    tc.Controls.Add(rBtn)
                    tc.HorizontalAlign = HorizontalAlign.Center
                End If
            End If

            If bol Then
                tc.ColumnSpan = cols - 1
                tr.Cells.Add(tc)
                Exit For
            Else
                tr.Cells.Add(tc)
            End If
        Next j

        tbl.Rows.Add(tr)                          
    Next i
End Sub

Calculate Score function

计算分数函数

    Private Sub subCalculateScore()
    Dim tblQs As Table = CType(Me.phQuestionnaire.FindControl("tblQs"), Table)
    Dim rb As New RadioButton
    Dim score As Integer = 0

    If Me.phQuestionnaire.FindControl("tblQs") Is Nothing Then
    Else
        For Each tr As TableRow In tblQs.Rows
            For Each tc As TableCell In tr.Cells
                For Each c As Control In tc.Controls
                    If c.GetType.ToString = rb.GetType.ToString Then
                        Dim rBtn As RadioButton = CType(c, RadioButton)
                        If rBtn.Checked Then
                            Dim strScore As String = rBtn.InputAttributes("value")
                            score += CInt(strScore)
                        End If
                    End If
                Next
            Next
        Next
    End If

    Me.Label1.Text = score
End Sub

View source for the dynamic generated table

查看动态生成表的源

  <table id="tblQs" cellspacing="0" cellpadding="0" border="0" style="border-width:1px;border-style:solid;width:500px;border-collapse:collapse;"><tr>           
<td style="border-width:1px;border-style:solid;"><span>No.</span></td>
<td style="border-width:1px;border-style:solid;"><span>Question</span></td>
<td style="border-width:1px;border-style:solid;"><span>dislike</span></td>
<td style="border-width:1px;border-style:solid;"><span>normal</span></td>
<td style="border-width:1px;border-style:solid;"><span>like</span></td>
<td style="border-width:1px;border-style:solid;"><span>vry likes</span></td></tr><tr>
<td style="border-width:1px;border-style:solid;"><span>1</span></td>
<td style="border-width:1px;border-style:solid;"><span>question 1</span></td>
<td style="border-width:1px;border-style:solid;">
    <input id="rBtn_1_0" type="radio" name="rBtn1" value="rBtn_1_0" value="0" /></td>
<td style="border-width:1px;border-style:solid;">
    <input id="rBtn_1_1" type="radio" name="rBtn1" value="rBtn_1_1" value="1" /></td>
<td style="border-width:1px;border-style:solid;">
    <input id="rBtn_1_2" type="radio" name="rBtn1" value="rBtn_1_2" checked="checked" value="2" /></td>
<td style="border-width:1px;border-style:solid;">
    <input id="rBtn_1_3" type="radio" name="rBtn1" value="rBtn_1_3" value="3" /></td></tr></table>

3 个解决方案

#1


If the names of the generated radio button groups are predictable enough, you could get their values by inspecting the Request.Form collection. Assuming the group names are rBtn1, rBtn2, etc, the post data will look something like rBtn1=6&rBtn2=7. That means you can do this:

如果生成的单选按钮组的名称足够可预测,则可以通过检查Request.Form集合来获取其值。假设组名是rBtn1,rBtn2等,后期数据看起来像rBtn1 = 6&rBtn2 = 7。这意味着你可以这样做:

Dim i as Integer
Dim score as Integer = 0
For i = 1 To expectedNumRows
    score += CInt(Request.Form("rBtn" & i)) 
Next

This will help you work around the fact that the controls that were generated before no-longer exist. You should poke around in the debugger and inspect the Request.Form collection so you can get familiar with what's in there.

这将帮助您解决在不再存在之前生成的控件这一事实。您应该在调试器中查看并检查Request.Form集合,以便您可以熟悉其中的内容。

(my apologies if my VB.NET is incorrect; I'm used to C#)

(我的道歉,如果我的VB.NET不正确;我已经习惯了C#)

#2


Thank you Jacob for his solution.

谢谢雅各布的解决方案。

I am able to calculate the score by making some modification for the ID assignment.

我可以通过对ID分配进行一些修改来计算分数。

I added its value at the back of the id since the value generated is the same with the ID as shown in the view source

我在id的后面添加了它的值,因为生成的值与视图源中显示的ID相同

rBtn.ID = "rBtn[" & rowCnt & "][" & colCnt & "]_" & value (eg. rBtn[1][0]_2 )

Then, i used substring to get and calculate the score as shown in the subCalculateScore function below:

然后,我使用substring来获取并计算得分,如下面的subCalculateScore函数所示:

 Private Function subCalulateScore() As Integer
    Dim score As Integer = 0
    Dim expectedNumRows As Integer = Me.qsNum.Text
    For i As Integer = 1 To expectedNumRows
        Dim strBtn As String = Request.Form("rBtn" & i)
        If Not strBtn Is Nothing Then
            If strBtn.LastIndexOf("_") <> -1 Then
                Dim strScore As String = strBtn.Substring(strBtn.LastIndexOf("_") + 1)
                score += CInt(strScore)
            End If
        End If
    Next

    Return score
End Function

Haha.. sound like a lousy way to do it :p

哈哈......听起来像是一种糟糕的方式:p

Once again, thanks for your help, Jacob.

雅各布再次感谢你的帮助。

Always welcome for any other solution ^^

随时欢迎任何其他解决方案^^

#3


I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.

我昨天想通过在loadviewstateevent被触发后立即加载控制树,你可以让你的应用程序正常工作。如果你覆盖loadviewstate事件,调用mybase.loadviewstate,然后把你自己的代码重新生成后面的控件,这些控件的值将在页面加载时可用。在我的一个应用程序中,我使用viewstate字段来保存可用于重新创建这些控件的ID或数组信息。

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
    MyBase.LoadViewState(savedState)
    If IsPostBack Then
        CreateMyControls()
    End If
End Sub

#1


If the names of the generated radio button groups are predictable enough, you could get their values by inspecting the Request.Form collection. Assuming the group names are rBtn1, rBtn2, etc, the post data will look something like rBtn1=6&rBtn2=7. That means you can do this:

如果生成的单选按钮组的名称足够可预测,则可以通过检查Request.Form集合来获取其值。假设组名是rBtn1,rBtn2等,后期数据看起来像rBtn1 = 6&rBtn2 = 7。这意味着你可以这样做:

Dim i as Integer
Dim score as Integer = 0
For i = 1 To expectedNumRows
    score += CInt(Request.Form("rBtn" & i)) 
Next

This will help you work around the fact that the controls that were generated before no-longer exist. You should poke around in the debugger and inspect the Request.Form collection so you can get familiar with what's in there.

这将帮助您解决在不再存在之前生成的控件这一事实。您应该在调试器中查看并检查Request.Form集合,以便您可以熟悉其中的内容。

(my apologies if my VB.NET is incorrect; I'm used to C#)

(我的道歉,如果我的VB.NET不正确;我已经习惯了C#)

#2


Thank you Jacob for his solution.

谢谢雅各布的解决方案。

I am able to calculate the score by making some modification for the ID assignment.

我可以通过对ID分配进行一些修改来计算分数。

I added its value at the back of the id since the value generated is the same with the ID as shown in the view source

我在id的后面添加了它的值,因为生成的值与视图源中显示的ID相同

rBtn.ID = "rBtn[" & rowCnt & "][" & colCnt & "]_" & value (eg. rBtn[1][0]_2 )

Then, i used substring to get and calculate the score as shown in the subCalculateScore function below:

然后,我使用substring来获取并计算得分,如下面的subCalculateScore函数所示:

 Private Function subCalulateScore() As Integer
    Dim score As Integer = 0
    Dim expectedNumRows As Integer = Me.qsNum.Text
    For i As Integer = 1 To expectedNumRows
        Dim strBtn As String = Request.Form("rBtn" & i)
        If Not strBtn Is Nothing Then
            If strBtn.LastIndexOf("_") <> -1 Then
                Dim strScore As String = strBtn.Substring(strBtn.LastIndexOf("_") + 1)
                score += CInt(strScore)
            End If
        End If
    Next

    Return score
End Function

Haha.. sound like a lousy way to do it :p

哈哈......听起来像是一种糟糕的方式:p

Once again, thanks for your help, Jacob.

雅各布再次感谢你的帮助。

Always welcome for any other solution ^^

随时欢迎任何其他解决方案^^

#3


I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.

我昨天想通过在loadviewstateevent被触发后立即加载控制树,你可以让你的应用程序正常工作。如果你覆盖loadviewstate事件,调用mybase.loadviewstate,然后把你自己的代码重新生成后面的控件,这些控件的值将在页面加载时可用。在我的一个应用程序中,我使用viewstate字段来保存可用于重新创建这些控件的ID或数组信息。

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
    MyBase.LoadViewState(savedState)
    If IsPostBack Then
        CreateMyControls()
    End If
End Sub