提问人:Eric Staples 提问时间:10/31/2023 更新时间:11/1/2023 访问量:30
更改 CheckBox 控件 asp.net,如何触发客户端 AND 服务器端事件
When asp.net CheckBox control is changed, how to fire client side AND server side events
问:
我在网格视图中有一个 asp.net 复选框。 它在 OnClick 中有一些 javascript 来确认操作员希望继续。 它还在 OnCheckedChanged 事件上有一些服务器端代码。
客户端代码正在执行,但服务器端代码不会被触发,无论操作员是否选择继续。 我已经通过添加一些断点来确认这一点。
如果删除 OnClick 客户端代码,则服务器端代码将正确执行。
任何关于我做错了什么的建议将不胜感激。
代码如下:
<asp:CheckBox ID="InclSectionCB" OnClick="return ProceedYN();" OnCheckedChanged="InclSectionCBChanged" runat="server" AutoPostBack="True" />
<script type="text/javascript">
function ProceedYN() {
return confirm('Proceed?');
}
</script>
我希望在选中/取消选中复选框时,步骤将是:
- 客户端 javascript 会提示操作员是否要继续。 2a) 如果操作员选择“确定”,则将更改复选框,并执行 InclSectionCBChanged 中的服务器端代码。 2b) 如果操作员选择“取消”,则不会更改复选框,并且不会执行 InclSectionCBChanged 中的服务器端代码。
正在发生的事情是:
- 客户端 javascript 会提示操作员是否要继续。(正确) 2a) 如果操作员选择“确定”,则 Checkbox 已更改,但不会执行 InclSectionCBChanged 中的服务器端代码。 2b) 如果操作员选择“取消”,则不会更改复选框,并且不会执行 InclSectionCBChanged 中的服务器端代码。
答:
好的,虽然我们共同为按钮(客户端和服务器端)单击事件编写了 2 个单击事件,但在复选框的情况下?
事实证明,只有一个点击事件,因此 asp.net 系统别无选择,只能将两个点击事件合并到一个通用例程中。(客户端 + 服务器端事件在 JavaScript 中合并为一个事件)。
这意味着您的第一个代码(客户端 JavaScript 单击)必须以不同的方式工作。
如果用户点击取消,则调用代码(请注意,此处注意,我声明了 CALLING 代码!!)必须停止,并返回 false 并退出代码存根。
但是,如果用户点击 ok,那么我们必须让调用代码 CONTINUE 然后运行服务器端 click 事件。
您可以通过检查生成的 JavaScript 来查看此效果。
如果我有一个这样的复选框:
<asp:CheckBox ID="CheckBox1" runat="server"
AutoPostBack="true"
OnCheckedChanged="CheckBox1_CheckedChanged"
onclick="return myjsclick(this)"
/>
如前所述,asp.net 将 OnCheckedChanged 代码和 onclick 代码合并到一个 JavaScript 代码块中(实际上没有 2 个单独的事件)。
因此,上面被转换为:
<input id="CheckBox1"
type="checkbox"
name="CheckBox1"
onclick="return myjsclick(this);setTimeout('__doPostBack(\'CheckBox1\',\'\')', 0)">
因此,请记住,您的 onclick(客户端)代码将与服务器端表达式(运行/触发服务器端代码隐藏的__doPostBack)相结合。
但是,在上面,由于我们总是返回 myjsclick(),因此上述代码位将退出并且永远不会继续运行和调用/运行服务器端代码。
因此,我们必须重新编写客户端的点击例程,以继续运行表达式后面的代码,但只有在用户确认对话框时才这样做。
这意味着如果用户取消,那么我们退出代码,但如果用户点击确认,那么我们将继续运行将/将/确实遵循我们的 onclick 代码的代码。
因此,我们可以这样编写代码:
<asp:CheckBox ID="CheckBox1" runat="server"
AutoPostBack="true"
OnCheckedChanged="CheckBox1_CheckedChanged"
onclick="if (!myjsclick(this)) {return false};"
/>
因此,如果表达式为 false,则返回 false(并退出代码)。但是,如果点击 ok,则 {return false} 将不会运行,但上述表达式后面的任何代码将继续运行。
上述内容在编译后会变成这个标记:
<input id="CheckBox1"
type="checkbox"
name="CheckBox1"
onclick="if (!myjsclick(this)) {return false};setTimeout('__doPostBack(\'CheckBox1\',\'\')', 0)">
所以,现在正如你所看到的,如果用户点击取消,那么上面的 JavaScript 代码将退出,但如果你点击 ok,那么表达式后面的代码行将运行。如前所述,客户端和服务器端事件都合并到一个 JavaScript 代码中,因此我们必须更改此类“确认”代码的编写方式。
我应该指出,当想要一个带有图标的按钮时,我经常使用上述按钮,因此我使用标准按钮,而不是 asp.net 按钮。它们的工作方式大致相同,但您必须再次使用上述技巧并“假设”您的点击事件和服务器事件合并为一个 JavaScript 代码。
因此,在上面使用复选框或标准按钮(使用 runat=server)执行上述操作时,我们得到了以下内容:
<button id="cmdViewPeople" runat="server" type="button"
onserverclick="cmdViewPeople_ServerClick"
onclick="if !(myconfirm(this) {return false};"
class="btn myshadow">
<span class="fa fa-bed fa-lg"> Booking Details</span>
</button>
上面的按钮如下所示:
因此,使用“按钮”而不是 asp.net 按钮的唯一原因是在该按钮中包含该图标(字体真棒)。但请注意,该按钮如何同时具有客户端单击和服务器端。只需记住与复选框相同的规则,该规则适用于按钮示例。
所以,让我们把这些放在一起,并在网格视图中执行此操作。
我们将有条件地运行该复选框,然后在代码隐藏中对给定的 GridView 复选框行单击执行操作。
因此,我们现在有这个简单的标记:
<h3><i>Hotels and Bookings</i></h3>
<asp:GridView ID="GVHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover"
Width="50%">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel" />
<asp:BoundField DataField="Description" HeaderText="Descriptioin" />
<asp:TemplateField HeaderText="Set Hotel Active"
ItemStyle-HorizontalAlign="Center" ItemStyle-Width="130px">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
AutoPostBack="true"
OnCheckedChanged="CheckBox1_CheckedChanged"
onclick="if (!myjsclick(this)) {return false};" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<script>
function myjsclick() {
return confirm("Activing this hotel can cost money\nPlease confrim")
}
</script>
加载网格的代码是这样的:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
GVHotels.DataSource = MyRst("SELECT * FROM tblHotelsA
ORDER BY HotelName")
GVHotels.DataBind()
End Sub
复选框的代码隐藏。请注意,服务器端复选框代码如何使用 NamingContainer 来显示 GridView 行。请注意,NamingContainer 相当方便,因为从那时起,我们省去了专用的 GridView 行命令。使用 NamingContainer 适用于复选框、组合框,甚至只是在 GridView 中单击一个简单的按钮来获取当前的 GridView 行信息。
因此,该代码如下所示:
Protected Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs)
Dim chk As CheckBox = sender
Dim gRow As GridViewRow = chk.NamingContainer
Debug.Print($"Row index click = {gRow.RowIndex}")
' get hidden non exposed database PK value
Dim intPK As Integer = GVHotels.DataKeys(gRow.RowIndex)("ID")
Debug.Print($"Database PK value = {intPK}")
Debug.Print($"Check box checked value = {chk.Checked}")
' code here to do whatever.
Dim cmdSQL As New SqlCommand(
"UPDATE tblHotels SET Active = @Active
WHERE ID = @ID")
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = intPK
cmdSQL.Parameters.Add("@Active", SqlDbType.Bit).Value = chk.Checked
MyRstPE(cmdSQL)
End Sub
因此,在运行时,我们会得到这样的效果:
在服务器端的 Immediate 窗口中,我们看到:
Row index click = 0
Database PK value = 17
Check box checked value = True
因此,使用上述代码可以具有行单击索引、数据库键,甚至是该行单击的任何值。
评论