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