views:

1712

answers:

3

Hi guys,

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.

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

     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>
A: 

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:

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.

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

Jacob
Hi Jacob. Thank you for your reply. I get what you mean there.As you can see that in my Populate Dynamic Table function, I was trying to assign value for it using inputAttributes. However, this is not working and the value found from the debugger was same with its ID as we can be found in the view source as the edited post.Can u give me any idea to set value for the dynamically generated radio button?I would be very appreciated for your help and your suggestion/solution.Thank you very much :)
A: 

Thank you Jacob for his solution.

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

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

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:

 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

Once again, thanks for your help, Jacob.

Always welcome for any other solution ^^

A: 

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.

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