2

コントロールを Web フォームに動的に挿入するプログラムを作成しています。変数に応じて、テキスト ボックス、ラジオ ボタンのセット、またはチェックボックスのセットのいずれかを追加します。後で、ユーザーが送信ボタンをクリックした後、ユーザーが正しい回答を送信しているかどうかを判断するためにコントロールを使用する必要がありますが、コントロールの ID を参照しようとすると、「txtAnser が宣言されていません。アクセスできない可能性があります」というメッセージが表示されます。保護レベルのためです。

.aspx ページは次のとおりです (マスター ページの標準コンテンツ ページです)。

<%@ Page Title="" Language="VB" MasterPageFile="~/top.master" AutoEventWireup="false" 
CodeFile="test_page.aspx.vb" Inherits="Default2" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="PageContent" Runat="Server">
    <asp:SqlDataSource ID="sdsQuestionPuller" runat="server" 
    ConnectionString="<%$ ConnectionStrings:SchoolhouseConnectionString6 %>" 
    SelectCommand="SELECT QuestionText, AnswerType, PossibleAnswers,    CorrectAnswers        
    FROM Questions WHERE (SubjectID = @SubjectID) AND (QuestionOrder = @QuestionOrder)">
    <SelectParameters>
        <asp:SessionParameter Name="SubjectID" SessionField="SubjectID" />
        <asp:SessionParameter Name="QuestionOrder" SessionField="PageNumber" />
    </SelectParameters>
</asp:SqlDataSource>
    <asp:SqlDataSource ID="sdsMaxQuestions" runat="server" 
        ConnectionString="<%$ ConnectionStrings:SchoolhouseConnectionString7 %>" 
        SelectCommand="SELECT MAX(QuestionOrder) AS LastQuestion FROM Questions GROUP     BY SubjectID HAVING (SubjectID = @SubjectID)">
        <SelectParameters>
            <asp:SessionParameter Name="SubjectID" SessionField="SubjectID" />
        </SelectParameters>
    </asp:SqlDataSource>
<div>
    <asp:Label ID="lblInstructionHolder" runat="server"></asp:Label>
</div>
<div>
    <asp:Label ID="lblQuestionHolder" runat="server"></asp:Label>
</div>
    <asp:PlaceHolder ID="plhQuestionHolder" runat="server"></asp:PlaceHolder>
<div>
    <asp:Button ID="btnSubmit" Text="Submit" runat="server" />
</div>
</asp:Content>

ここにコード ビハインドがあります。select case ステートメントで txtAnswer コントロールを参照しようとすると、送信ボタンのクリック イベントで問題が発生します。

Imports System.Data

Partial Class Default2
    Inherits System.Web.UI.Page

    Dim intMaxPage As Integer
    'QuestionText, AnswerType, PossibleAnswers, CorrectAnswers
    Dim strQuestion As String
    Dim strQuestionType As String
    Dim astrPossibleAnswers() As String
    Dim intNumberOfPossAnswers As Integer
    Dim astrCorrectAnswers() As String
    Dim intNumberOfCorrectAnswers As Integer

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Load up the variables(make sure data is retrieved, create a view from the source, retrieve the only row, assing the item(s) from the row to variables)
        sdsMaxQuestions.DataBind()
        Dim dtvLastPageView As DataView = CType(sdsMaxQuestions.Select(DataSourceSelectArguments.Empty), DataView)
        Dim dtrLastPageRow As DataRowView = dtvLastPageView.Item(0)
        intMaxPage = CInt(Trim(dtrLastPageRow.Item(0).ToString))

        Dim dtvQuestionsView As DataView = CType(sdsQuestionPuller.Select(DataSourceSelectArguments.Empty), DataView)
        Dim dtrQuestionsRow As DataRowView = dtvQuestionsView.Item(0)
        strQuestion = Trim(dtrQuestionsRow.Item(0).ToString)
        strQuestionType = Trim(dtrQuestionsRow.Item(1).ToString)
        astrPossibleAnswers = Split(Trim(dtrQuestionsRow.Item(2).ToString), ";")
        intNumberOfPossAnswers = astrPossibleAnswers.Count
        astrCorrectAnswers = Split(Trim(dtrQuestionsRow.Item(3).ToString), ";")
        intNumberOfCorrectAnswers = astrCorrectAnswers.Count

        'Finish loading controls
        lblQuestionHolder.Text = strQuestion
        Select Case strQuestionType
            Case "checkbox"
                lblInstructionHolder.Text = "Choose the correct answer(s)."
            Case "radio"
                lblInstructionHolder.Text = "Choose the best answer."
            Case "fillintheblank"
                lblInstructionHolder.Text = "Please fill in the blank, case doesn't count, spelling does."
            Case Else
                lblInstructionHolder.Text = "Somethings wrong, contact admin"
        End Select

        'Generate the controls for answers...
        GenerateControls()

    End Sub

    Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
        'Declare the variables, get any existing values, then check to see if the answer is correct, display a message and go to the next page or store the score.
        Dim intNumberRight As Integer = 0
        Dim intNumberTotal As Integer = 0

        If Not (Session("NumberRight") = Nothing) Then
            intNumberRight = CInt(Session("NumberRight"))
        End If
        If Not (Session("NumberTotal") = Nothing) Then
            intNumberTotal = CInt(Session("NumberTotal"))
        End If

        Select Case strQuestionType
            Case "checkbox"

            Case "radio"

            Case "fillintheblank"
                'Here is where I am having issues
                If txtAnswer Is Not Nothing Then

                End If
                If txtAnswer.text.ToLower = astrCorrectAnswers(0).ToLower Then

                End If
            Case Else
                MsgBox("Somethings wrong, contact admin")
        End Select

        If intMaxPage = CType(Session("PageNumber"), Integer) Then
            Response.Redirect("user_landing.aspx")
        Else
            Session("PageNumber") = CType(Session("PageNumber"), Integer) + 1
            Response.Redirect("test_page.aspx")
        End If
    End Sub

    Private Sub GenerateControls()
        'Make the correct controls depending on the type
        Dim conDivHolder As HtmlGenericControl = New HtmlGenericControl("div")

        Select Case strQuestionType
            Case "checkbox"
                For i As Integer = 0 To intNumberOfPossAnswers - 1
                    Dim chkAnswer As CheckBox = New CheckBox
                    With chkAnswer
                        .ID = "chkAnswer" + i.ToString
                        .Text = astrPossibleAnswers(i)
                    End With
                    conDivHolder.Controls.Add(chkAnswer)
                Next

            Case "radio"
                For i As Integer = 0 To intNumberOfPossAnswers - 1
                    Dim rdoAnswer As RadioButton = New RadioButton
                    With rdoAnswer
                        .ID = "rdoAnswer" + i.ToString
                        .Text = astrPossibleAnswers(i)
                        .GroupName = "rdoGroup"
                    End With
                    conDivHolder.Controls.Add(rdoAnswer)
                Next

            Case "fillintheblank"
                Dim txtAnswer As TextBox = New TextBox
                txtAnswer.ID = "txtAnswer"
                conDivHolder.Controls.Add(txtAnswer)

            Case Else
                Dim lblOops As Label = New Label
                lblOops.Text = "Oops, contact admin"
                conDivHolder.Controls.Add(lblOops)
        End Select

        plhQuestionHolder.Controls.Add(conDivHolder)
    End Sub

End Class

誰かが私がしなければならないことを指摘できれば、私はそれを感謝します.

ありがとう、サイモン

4

2 に答える 2

2

まず、Page_Load(PostBackかどうか)でコントロールを生成しているため、送信ボタンがクリックされる前のtxtAnswerの状態が何であれ、現在はなくなっています。txtAnswerは初期状態で再生成されています。IsPostBackがfalseの場合にのみ、コントロールを動的にレンダリングする必要があります。

次に、Is NotNothingifステートメントブロック内のtxtAnswerのTextプロパティにアクセスする必要があります。そうしないと、null参照例外が発生する可能性があります。

第三に、TextBoxコントロールへの参照を取得するには、プレースホルダー内のIDでコントロールを検索します(これはC#で行っています。自分でVBに変換できます)。

コントロールを再帰的に検索する関数を定義します。

protected Control FindControl(Control parent, string controlID)
{
  Control control = parent.FindControlByID("controlID");

  if (control != null) 
  {
    return control;
  }

  foreach(Control child in control.Controls)
  {
    Control childControl = FindControl(child , controlID);

    if (childControl != null) 
    {
      return childControl;
    }
  }

  return null;
}

再帰検索関数を呼び出します。

Control ctrl = FindControl(plhQuestionHolder, "txtAnswer");

このコードは実際にはテストされていないので、そのまま機能しない場合は私に怒鳴らないでください。これは単なるガイドです。

于 2011-03-20T14:35:18.153 に答える
1

動的コントロールへの参照を取得するには、プレースホルダーで再帰的なFindControlを実行する必要があります。これを試して

Public Shared Function FindChildControl(start As Control, id As String) As Control
    If start IsNot Nothing Then
        Dim foundControl As Control
        foundControl = start.FindControl(id)

        If foundControl IsNot Nothing Then
            Return foundControl
        End If

        For Each c As Control In start.Controls
            foundControl = FindChildControl(c, id)
            If foundControl IsNot Nothing Then
                Return foundControl
            End If
        Next
    End If
    Return Nothing
End Function

と電話

txtAnswer = FindChildControl(plhQuestionHolder, "txtAnswer")
If txtAnswer Is Not Nothing Then

End If
于 2011-03-20T14:30:55.363 に答える