更改 CheckBox 控件 asp.net,如何触发客户端 AND 服务器端事件

When asp.net CheckBox control is changed, how to fire client side AND server side events

提问人:Eric Staples 提问时间:10/31/2023 更新时间:11/1/2023 访问量:30

问:

我在网格视图中有一个 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>

我希望在选中/取消选中复选框时,步骤将是:

  1. 客户端 javascript 会提示操作员是否要继续。 2a) 如果操作员选择“确定”,则将更改复选框,并执行 InclSectionCBChanged 中的服务器端代码。 2b) 如果操作员选择“取消”,则不会更改复选框,并且不会执行 InclSectionCBChanged 中的服务器端代码。

正在发生的事情是:

  1. 客户端 javascript 会提示操作员是否要继续。(正确) 2a) 如果操作员选择“确定”,则 Checkbox 已更改,但不会执行 InclSectionCBChanged 中的服务器端代码。 2b) 如果操作员选择“取消”,则不会更改复选框,并且不会执行 InclSectionCBChanged 中的服务器端代码。
asp.net 复选框 服务器端 客户端

评论


答:

0赞 Albert D. Kallal 11/1/2023 #1

好的,虽然我们共同为按钮(客户端和服务器端)单击事件编写了 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>

上面的按钮如下所示:

enter image description here

因此,使用“按钮”而不是 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

因此,在运行时,我们会得到这样的效果:

enter image description here

在服务器端的 Immediate 窗口中,我们看到:

Row index click = 0
Database PK value = 17
Check box checked value = True

因此,使用上述代码可以具有行单击索引、数据库键,甚至是该行单击的任何值。

评论

1赞 Eric Staples 11/1/2023
很棒的回答阿尔伯特,感谢您的详细回复!
0赞 Albert D. Kallal 11/1/2023
听起来不错 - 如果这对您有帮助,请标记为答案......