在旧的ASP.NET Webforms应用程序中,我需要在用户单击按钮时更新数据库表,具体取决于检查表单上的复选框,使用相应标签中的值进行更新。
它不起作用;但是,Winforms“test”应用程序中几乎完全相同的代码确实有效。
FormLoad(Winforms)和Page_Load(Webforms)代码运行正常;没有必要显示所有代码;他们都使用成对的标签/复选框控件填充表单/页面。
要显示它们彼此之间的区别,但是:当动态创建控件时,它们会分配Tag值(Winforms)或ID(Webforms)字符串值(下面有更多内容)。
在工作(Winforms)代码中,它以这种方式完成:
Dim lblCompanyName = New Label()
lblCompanyName.Tag = i.ToString()
lblCompanyName.Text = reader.Item(0).ToString()
Me.Controls.Add(lblCompanyName)
Dim ckbx = New CheckBox()
ckbx.Tag = i.ToString()
ckbx.Checked = True
Me.Controls.Add(ckbx)
在非工作(Webforms)代码中,它以这种方式完成:
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)
除了表单/页面加载代码之外,还有其他三个代码块:一个按钮单击事件处理程序,以及该处理程序调用的两个实用程序方法。
Winforms应用程序中使用.NET Framework 4.5的代码可以正常工作(单击按钮时更新数据库表);使用.NET Framework 2的Webforms应用程序中的代码不会像应该的那样更新数据库表 - 但是没有显示错误的页面,只是甜蜜的笑容和懒洋洋地依赖于它的桂冠。
我在两者之间的代码中看到的唯一真正区别是,在一种情况下(Winforms应用程序),动态创建的控件的Tag属性被赋值,而在另一种情况下(Webforms站点),动态创建的控件的ID属性是指定的。顺便说一句,这两种技术似乎都没有其他属性可用(Winforms似乎无法访问控件的ID属性,而Webforms似乎无法访问控件的Tag属性)。
相关的区别是没有两个控件可以具有相同的ID(Webforms);因此,我必须将“lbl”添加到Label控件ID,将“ckbx”添加到Checkbox控件ID(每对共享相同的编号,以便“lbl1”和“ckbx1”是匹配的对,“lbl42”和“ ckbx42“是匹配对等。”
为什么Webforms应用程序中几乎相同的代码无法更新数据库?
以下是这三个代码块的工作(Winforms / .NET 4.5)代码:
Private Sub Button1_Click( sender As Object, e As EventArgs) Handles Button1.Click
Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;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 curTagVal As String
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
If DirectCast(cntrl, CheckBox).Checked = True Then
curTagVal = CStr(DirectCast(cntrl, CheckBox).Tag)
coName = GetLabelTextForTag(curTagVal)
argVals = GetArgValsForCompanyName(coName)
_Unit = argVals(0)
_MemberNo = argVals(1)
_CustNo = argVals(2)
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
Protected Function GetLabelTextForTag(tagVal As String) As String
Dim CoName As String = ""
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is Label Then
If DirectCast(cntrl, Label).Tag.ToString() = tagVal Then
CoName = DirectCast(cntrl, Label).Text
Exit For
End If
End If
Next
Return CoName
End Function
Protected Function GetArgValsForCompanyName(coName As String) As String()
Dim args(2) As String
Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"),
cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)
con.Open()
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName
Using reader As SqlDataReader = cmd.ExecuteReader
While reader.Read
args(0) = reader.Item(0).ToString()
args(1) = reader.Item(1).ToString()
args(2) = reader.Item(2).ToString()
End While
End Using
End Using
Return args
End Function
...这里是相应代码块的非工作(Webforms / .NET 2.0)代码:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;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
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
If DirectCast(cntrl, CheckBox).Checked = True Then
curCheckboxIDVal = CStr(DirectCast(cntrl, CheckBox).ID)
coName = GetLabelTextForID(curCheckboxIDVal)
argVals = GetArgValsForCompanyName(coName)
_Unit = argVals(0)
_MemberNo = argVals(1)
_CustNo = argVals(2)
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
Protected Function GetLabelTextForID(ckbxIDVal As String) As String
Dim CoName As String = ""
Dim _idVal As String = ckbxIDVal
Dim numberLen As Integer = _idVal.Length - "ckbx".Length
_idVal = _idVal.Substring("ckbx".Length, numberLen)
LabelDebug.Text = _idVal
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is Label Then
If DirectCast(cntrl, Label).ID = "lbl" + _idVal Then
CoName = DirectCast(cntrl, Label).Text
Exit For
End If
End If
Next
Return CoName
End Function
Protected Function GetArgValsForCompanyName(coName As String) As String()
Dim args(2) As String
Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"), _
cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)
con.Open()
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName
Using reader As SqlDataReader = cmd.ExecuteReader
While reader.Read
args(0) = reader.Item(0).ToString()
args(1) = reader.Item(1).ToString()
args(2) = reader.Item(2).ToString()
End While
End Using
End Using
Return args
End Function
正如您所看到的,代码实际上是相同的,但结果(成功/失败)是截然相反的。为什么呢?
显然这条线路失败了:
If TypeOf cntrl Is CheckBox Then
虽然页面上有复选框,但该测试失败。为什么呢?
我知道这是因为我在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"
. . .
写给Label2的最后一个文本是“来自foreach的标签2文本”。
所以,“如果TypeOf cntrl是CheckBox然后”失败。
是否看不到复选框,因为它们是动态创建的?如果是这样,我该如何解决这个问题?
当我将其添加到相应的.aspx文件时:
<%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb"
Inherits="pages_custmaint_categoryadmin" %>
(添加了“IsPostback =”true“”部分)
...“IsPostback”在红色波浪形中得到了强调,当我运行它时,我得到了:
Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Error parsing attribute 'ispostback': The 'ispostback' property is read-only and cannot be set.
Source Error:
Line 1: <%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb" Inherits="pages_custmaint_categoryadmin" %>
Line 2:
Line 3: <!DOCTYPE html>
现在这里有一些超级怪异的东西,在我看来:我在Webform上放了一个复选框,然后再次运行它。即使表单上有可见的设计时复选框,它仍然没有超过“If TypeOf cntrl Is CheckBox Then”测试; Label2.Text的最后一次更新仍然是“来自foreach的标签2文本”
Checkbox,特别是“具体”而不是动态的复选框怎么能不等同于复选框?!