为这篇冗长的帖子提前道歉,但我正在构建一个.NET页面遇到一些麻烦。
结束问题:如何在Page_Load子例程中检查动态创建的复选框的“已检查”属性?
DETAILS:基本上,我有一个VB.NET页面,它根据用户选择的数字动态创建一些表格行。因此,例如,如果用户从下拉列表中选择“3”,则页面回发并创建三个表行。每行包含几个文本框,一个下拉列表和一个复选框(这些都是.NET表单控件而不是纯HTML控件,我应该指出)。
通常,用户会在表单控件中输入一些详细信息,然后单击“提交”按钮,之后页面将遍历每一行,并将数据插入到SQL Server表中。
但是如果用户勾选该行的复选框,则表示该页面将忽略该行,并且当用户单击“提交”时,不会将该行数据插入数据库。
这很好用,但是有问题。如果用户单击“提交”并且表单控件中输入的某些值无效(例如,用户未输入其名称),则页面将不提交数据,而是显示错误向用户通知他们需要改变的值。但是,如果用户创建了三行,例如,但是决定“忽略”第三行(通过勾选复选框),那么当页面回发时,找到一些无效的条目,并将表单重新显示给用户以允许它们为了纠正任何错误,我宁愿页面完全没有呈现第三行。毕竟,他们原本选择创建三行,但后来决定只需要两行。因此,重新创建第三行是有道理的。
首先,我在 Page_Load 子例程中使用了与以下内容类似的代码:
If objCheckbox.Checked = False
' Render the row, and recreate the dynamic controls '
Else
' Dont render the row or any of the controls '
End If
但似乎发生的事情是 objCheckbox.Checked 总是返回 False ,即使勾选了复选框也是如此。加载页面后,表格行再次呈现,复选框中出现勾号,因此它不像回发时丢失的值。但在此我检查是否勾选了复选框,它总是返回 False ,呈现用户不需要的表格行。
有谁知道如何解决这个问题?我已经阅读了很多关于.NET ViewState和页面生命周期的文章,但我还没有找到有效的解决方案。我只需要能够在重新创建一些动态控件之前检查是否勾选了复选框。
我尝试了这个使用ViewState的替代代码,但无济于事:
If objIgnoreCheckbox.ViewState("Checked") = False Then
' Render the row, and recreate the dynamic controls '
Else
' Dont render the row or any of the controls '
End If
执行此操作时,我收到以下错误:
'System.Web.UI.Control.Protected Overridable ReadOnly Property ViewState()AsSystem.Web.UI.StateBag'在此上下文中无法访问,因为它是“受保护的”。
所以我尝试创建一个继承自Checkbox的自定义类,并尝试覆盖ViewState属性以使其公开,以便可以从中读取:
Public Class CheckboxControl
' Inherits all Checkbox properties and methods '
Inherits Checkbox
' Create the public ViewState property '
Public Overrides ReadOnly Property ViewState As StateBag
Get
Dim objChecked As Object = ViewState("Checked")
If Not (IsNothing(objChecked)) Then
Return objChecked
End If
End Get
End Property
End Class
但后来我基本上发现你不能用公共成员覆盖受保护的成员。我在创建新课程方面的经验很少,所以我很难过。
所以,如果有人能告诉我如何检查这个复选框,我会永远感激不尽!我花了整整一天的时间试图解决问题,但没有运气!
提前致谢!
答案 0 :(得分:2)
对于静态控件,控件的视图状态将在Page_Init
中恢复,这在Page_Load
之前发生,因此它们在Page_Load
中包含正确的值。动态控件是在Page_Load
中创建的,因此Page_Load
中的视图状态不正确,并且会在 Page_Load
之后恢复,但在调用之前事件处理程序。 MSDN says:
在运行Page_Load事件之后,但在调用控件事件处理方法之前,剩余的视图状态信息将加载到动态创建的控件中。
这就是Checked
返回false的原因,以及为什么更改CheckBox.ViewState
的可见性无法解决您的问题。
解决方案(未经测试,但我认为它应该可行):在Page_Load
中创建所有控件(甚至是那些您不想显示的控件) 。将CheckedChanged
上的事件处理程序附加到CheckBoxes(Page_Load
)。在Page_Load
完成后,ASP.NET将恢复新创建的控件的视图状态(这就是为什么在Page_Load中创建相同的控件很重要,这样ASP.NET才能正确将视图状态映射到控件),ASP.NET将为已更改的CheckBox调用事件处理程序。在那里,您可以删除不想显示的行。
这是添加事件处理程序的方法
AddHandler objCheckbox.CheckedChanged, AddressOf MyCheckedChangedFunction
这个函数看起来像这样:
Function MyCheckedChangedFunction(sender As Object, e As EventArgs)
Dim objCheckbox = DirectCast(sender, CheckBox)
... access objCheckbox.Changed and do something useful here ...
End Function