Why are Checkboxes not seen as being of type Check

2020-02-13 05:58发布

问题:

This question morphed from a previous one here.

It seems that the problem is actually this failure to recognize checkboxes as such - whether there's really a problem with updating the database once this conundrum is solved remains to be seen.

So here's the code:

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=entenhausen;PWD=pondscum"
    Dim upd8DML As String = "UPDATE CustomerCategoryLog SET Category = 'Exploding' WHERE Unit = @Unit And MemberNo = @MemberNo AND Custno = @CustNo"

    Dim coName As String
    Dim argVals(2) As String
    Dim _Unit As String
    Dim _MemberNo As String
    Dim _CustNo As String
    Dim curCheckboxIDVal As String
    Label2.Text="label 2 text from button1_click"
    LabelDebug.Text="label debug text from button1_click"

    For Each cntrl As Control In Me.Controls
            Label2.Text="label 2 text from foreach"
            If TypeOf cntrl Is CheckBox Then
                Label2.Text="label 2 text from is checkbox"
                If DirectCast(cntrl, CheckBox).Checked = True Then
                    Label2.Text="label 2 text from checked"
                    curCheckboxIDVal = CStr(DirectCast(cntrl, CheckBox).ID)
                    coName = GetLabelTextForID(curCheckboxIDVal)
                    argVals = GetArgValsForCompanyName(coName)
                    _Unit = argVals(0)
                    _MemberNo = argVals(1)
                    _CustNo = argVals(2)
                Label2.Text=_Unit
                LabelDebug.Text=_MemberNo
                    Using conn As New SqlConnection(connStr), _
                        cmd As New SqlCommand(upd8DML, conn)
                        cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 50).Value = _Unit
                        cmd.Parameters.Add("@MemberNo", SqlDbType.VarChar, 50).Value = _MemberNo
                        cmd.Parameters.Add("@CustNo", SqlDbType.VarChar, 50).Value = _CustNo
                        conn.Open
                        cmd.ExecuteScalar()
                    End Using
                End If
            End If
        Next
End Sub

I am updating Label2.Text to see how far the code gets - and it only gets to the "foreach" - this is the last value of Label2.Text: "label 2 text from foreach"

So this line:

If TypeOf cntrl Is CheckBox Then

...fails to equate to true.

Yet, not only do I have many dynamically-created Checkboxes on the form when the button is clicked, there is also one that I dropped there at design-time. NONE of these checkboxes are seen as checkboxes, obviously.

Why not? Why is the type of the checkbox control not evaluating to CheckBox?

NOTE: When I prepend "the whole shebang" like so:

System.Web.UI.WebControls.CheckBox

...it makes no difference; in fact, it grays out the "System.Web.UI.WebControls." portion.

UPDATE

That idea from Perry Mason inspirited me to try this:

For Each cntrl As Control In Me.Controls
    Label2.Text = "label 2 text from foreach"
    LabelDebug.Text = LabelDebug.Text+" "+cntrl.GetType().ToString+" "
    If TypeOf cntrl Is System.Web.UI.WebControls.CheckBox Then

...which shows this:

So a Checkbox (among other things) is seen simply as a "LiteralControl" apparently. Seems rather vague...

UPDATE 2

In response to Bradley Uffner, here is the code that adds the checkboxes:

For i As Integer = 0 To categoryDT.Rows.Count - 1
    ' for testing, limit count
    If i > 3 Then 'There are thousands...just grab enough to fit on the page without scrolling for now...
        Exit For
    End If
    Dim coName = New Label()
    ' Must prepend with something, as controls cannot share the same ID
    coName.ID = "lbl" + i.ToString()
    coName.Text = categoryDT.Rows(i)(0).ToString()
    formCustCatMaint.Controls.Add(coName)

    Dim chk = New CheckBox()
    chk.ID = "ckbx" + i.ToString()
    chk.Checked = True
    formCustCatMaint.Controls.Add(chk)

    ' Add a "line break" after each checkbox
    Dim l = New Label()
    l.Text = "<br>"
    formCustCatMaint.Controls.Add(l)
Next

UPDATE 3

On third thought, it may be that it is not that the Checkboxes are being seen as System.Web.UI.LiteralControl, but that they are not being seen at all - not even the one dropped on the form/page at design time.

Why do I propose this radical idea? Because only the following controls are enumerated:

LiteralControl
HtmlHead
LiteralControl
HtmlForm
LiteralControl

Yet thre are many more controls than that, even discounting the dynamically-generated Checkboxes. There is no button, unless it is one of the "LiteralControl"s.

Something is rotten as all get-out here.

UPDATE 4

Changing Page_Load to Page_Init (at Perry Mason's suggestion) did make a difference; I get this:

Multiple controls with the same ID 'lbl0' were found. Trace requires that controls have unique IDs. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Web.HttpException: Multiple controls with the same ID 'lbl0' were found. Trace requires that controls have unique IDs.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

UPDATE 5

I really don't get why there are multiple "lbl0"s because the i in the loop should automatically increment, right? This is the code:

For i As Integer = 0 To categoryDT.Rows.Count - 1
    ' for testing, limit count
    If i > 3 Then 'There are thousands...just grab enough a few for now...
        Exit For
    End If
    Dim coName = New Label()
    ' Must prepend with something, as controls cannot share the same ID
    coName.ID = "lbl" + i.ToString()
    coName.Text = categoryDT.Rows(i)(0).ToString()
    formCustCatMaint.Controls.Add(coName)

    Dim chk = New CheckBox()
    chk.ID = "ckbx" + i.ToString()
    chk.Checked = True
    formCustCatMaint.Controls.Add(chk)

    ' Add a "line break" after each checkbox
    Dim l = New Label()
    l.Text = "<br>"
    formCustCatMaint.Controls.Add(l)
Next

...and i is obviously incrementing because otherwise the "If i > 3" would never be true, which it is, because the number of Label/CheckBox pairs are indeed curtailed.

Could it be that Page_Init is called multiple times, and the second time it tries to add a second lbl0, and then the above occurs?

UPDATE 6

That must indeed be true (that Page_Init) is reached multiple times, because the following code prevented the err from occurring:

Dim PageAlreadyInitted As Boolean = False

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If PageAlreadyInitted = True Then Exit Sub
    PageAlreadyInitted = True

...but it makes no difference as far as Checkboxes being found in the loop through the controls - I still get only LiteralControls, no Buttons, Checkboxes, etc.

UPDATE 7

FWIW, the controls are being created as expected, as can be seen from this extract via "View Source":

<span id="lbl0"> AMC THEATRES - TYSON CORNER 16</span><input id="ckbx0" type="checkbox" name="ckbx0" checked="checked" /><span><br></span><span id="lbl1"> GSO AIRPORT - ACC</span><input id="ckbx1" type="checkbox" name="ckbx1" checked="checked" /><span><br></span><span id="lbl2"> LONGHORN - DES PLAINS</span><input id="ckbx2" type="checkbox" name="ckbx2" checked="checked" /><span><br></span><span id="lbl3"> MAGGIE'S </span><input id="ckbx3" type="checkbox" name="ckbx3" checked="checked" /><span><br></span><span id="lbl4"> OAKRIDGE NURSING & REHAB NO LGER FB 11296</span><input id="ckbx4" type="checkbox" name="ckbx4" checked="checked" /><span><br></span><span id="lbl5"> SKYPORT - WOODY CREEK B&C DIA C-C </span><input id="ckbx5" type="checkbox" name="ckbx5" checked="checked" /><span><br></span><span id="lbl6"> UNIV NORTH CAROLINA - CHARLOTTE - BAKERY #32936</span><input id="ckbx6" type="checkbox" name="ckbx6" checked="checked" /><span><br></span><span id="lbl7">"DRAKE ""SIMPLY TO GO/OLMSTED #2"</span><input id="ckbx7" type="checkbox" name="ckbx7" checked="checked" /><span><br></span><span id="lbl8">"DRAKE CENTER   SCS""OLD ACCOUNT"""</span><input id="ckbx8" type="checkbox" name="ckbx8" checked="checked" /><span><br></span><span id="lbl9">"HUT, THE - EMORY & HENRY"</span><input id="ckbx9" type="checkbox" name="ckbx9" checked="checked" /><span><br></span><span id="lbl10">"THOMAS MORE COLLEGE   SCS ""OLD"""</span><input id="ckbx10" type="checkbox" name="ckbx10" checked="checked" /><span><br></span><span id="lbl11">"WRIGHT STATE ""C"" STORE  SCS"</span><input id="ckbx11" type="checkbox" name="ckbx11" checked="checked" /><span><br></span>

回答1:

The fix ended up being simple, and even logical, in hindsight.

The controls are dynamically added to the form, like so:

formCustCatMaint.Controls.Add(coName) And so, replacing this line, in the loop:

For Each cntrl As Control In Me.Controls ...with this:

For Each cntrl As Control In formCustCatMaint.Controls And this line, in the GetLabelTextForID() function:

For Each cntrl As Control In Me.Controls ...with this:

For Each cntrl As Control In formCustCatMaint.Controls ...did the trick. The controls are being found, and the code is working as designed/originally expected.

Nebenbei bemerkt, this also works fine now:

If TypeOf cntrl Is CheckBox Then