如何使用www.example.com在两个不同的选项卡中打开同一页面时,获取网格视图中按钮单击事件的IDasp.net

siv3szwd  于 2022-11-26  发布在  .NET
关注(0)|答案(1)|浏览(79)

我有一个网格视图与图像按钮为每一个tr在asp和相同的网页是打开在两个不同的标签。
在第一个标签中:
对网格的第一个tr执行按钮点击事件,并在执行必要功能后重新加载网格。(删除第一个tr)
在第二个标签中:(无需重新加载页面)
当在第一个选项卡中已删除的第一个tr的按钮上执行单击事件时,下一个tr的ID将在asp按钮的命令参数中传递。
当在两个不同的选项卡中打开时,我如何解决这个问题,以便我可以在网格视图中正确检索按钮单击的ID?
当前代码:
按钮链接是asp:

<asp:ImageButton ImageUrl="~/images/btn_delete_sm.gif" ID="imgDelete"  runat="server" OnClientClick="return confirm('Are you sure you want to discontinue?');"  OnClick="btnDelete_Click" CommandArgument='<%#Eval("id")%>' />

VB语言:

Dim btnDetails As ImageButton = sender
Dim ID As String = btnDetails.CommandArgument.ToString()
xkftehaa

xkftehaa1#

其实这不重要。
您不是按行“index”删除,而是(应该是)按数据库PK ID删除,并且其中只有一个将永远存在。
因此,假设用户打开了两个浏览器(或两个选项卡),这并不重要。
因此,我们通常不会(也不会)通过某些行来解析数据,而实际上使用100% unquie数据库键id。
作为一个参考,我经常(事实上现在在大多数情况下)不使用GV内置的事件模型(在行索引改变时),甚至不使用命令arugment。(但是,如果你愿意,你仍然可以这样做)。
只需按下飞机上的Jane常规按钮,并以如下方式连接事件:
当然,通常情况下,你可以双击一个按钮来添加/创建/连接一个click事件。但是,当你把那个按钮放到GV中时,你不能双击desinger中的按钮来添加click事件(因为它嵌套在GV中)。
因此,您可以将按钮拖放到模板部分,然后在标记中简单键入

onclick=

当您点击“=”按钮时,intelisense会弹出此选项:

因此,选择创建新事件。您现在拥有以下标记:

<asp:GridView ID="GridView1" runat="server" Width="40%"
    AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table" GridLines="none">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
        <asp:BoundField DataField="LastName" HeaderText="LastName" />
        <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:TemplateField HeaderText="Description">
            <ItemTemplate>
                <asp:Label ID="lblDescript" runat="server"
                    Text='<%# Eval("Description")  %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Button ID="cmdDel" runat="server" Text="Delete"
                    CssClass="btn"
                    onclick="cmdDel_Click" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

我们要加载的代码如下:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then
        LoadData()
    End If

End Sub

Sub LoadData()

    Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
    Dim cmdSQL As New SqlCommand(strSQL)
    GridView1.DataSource = MyrstP(cmdSQL)
    GridView1.DataBind()

End Sub

而现在我们看到/有了这个:

好了,现在任何按钮代码都不会对行索引进行操作,而是对主键进行操作
因此,要删除的按钮代码可以是:

Protected Sub cmdDel_Click(sender As Object, e As EventArgs)

    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer

    Debug.Print("Row index click = " & gRow.RowIndex)
    Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
    Debug.Print("Hidden database PK value = " & intPK)

    ' delete the row from database
    Dim cmdSQL As New SqlCommand("DELETE FROM tblHotelsA WHERE ID = @ID")
    cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = intPK
    MyrstP(cmdSQL, True)

    ' refresh grid after delete
    LoadData()

End Sub

因此,在上面的步骤中,我们使用了隐藏的数据库ID。因此,如果用户再次尝试删除,也不会有任何影响。
请注意,我们实际上并没有使用行索引,而是使用数据库“PK”id进行操作。另外,请注意,非常接近,我们从未在标记中公开或显示数据库PK id,甚至也没有在GV中显示。我们为此使用了datakeys“id”设置。这不仅意味着我们从未在浏览器中公开或拥有数据库密钥客户端,而且更好的是,它是gridview(或listview等)的一个内置特性,用于管理数据库PK(主键)值的检索,并且它更加安全,因为这样的键永远不会暴露给客户端浏览器(也有利于安全性)。
因此,这里唯一真实的的挑战是,当然用户可能试图对不存在的行执行某些操作,但话又说回来,您可以并将在代码中处理此问题。
那么,如果操作被说成是编辑或做其他事情呢?那么,代码会发现/看到该行不再存在了。
在上面的代码中,像所有的开发人员一样,我厌倦了一遍又一遍地输入相同的代码,所以我使用了这个辅助例程:

Public Function MyrstP(cmdSQL As SqlCommand,
                       Optional cmdOnly As Boolean = False) As DataTable
    Dim rstData As New DataTable
    Using mycon As New SqlConnection(GetConstr)
        Using (cmdSQL)
            cmdSQL.Connection = mycon
            mycon.Open()
            If cmdOnly Then
                cmdSQL.ExecuteNonQuery()
            Else
                rstData.Load(cmdSQL.ExecuteReader)
            End If
        End Using
    End Using
    Return rstData
End Function

但是,假设我们放入一个编辑按钮来编辑该行。
比如说,我们将弹出一个编辑器,如下所示:

那么现在这个编辑按钮,如果其他用户删除了该行,它还能工作吗?
当然,因为编辑按钮代码如下所示:

Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)

    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer
    Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")

    Dim cmdSQL = New SqlCommand("SELECT * FROM tblHotelsA WHERE ID = @ID")
    cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = intPK
    Dim rstHotel As DataTable = MyrstP(cmdSQL)

    If rstHotel.Rows.Count > 0 Then
        Call EditOne(rstHotel)
    End If

End Sub

因此,由于所有数据操作都基于数据库PK,因此这并不重要。
当然,现在可能需要弹出一个消息框或类似的消息框,告诉用户该行不存在。
当然,在编辑,甚至删除之后,你无论如何都要刷新GV,这样用户仍然会没事(因为在编辑,或编辑尝试,或删除或其他任何事情之后,你无论如何都要/应该/必须/好主意刷新和重新加载GV。
因此,不,错误的行不会被删除,假设您基于PK执行每个数据操作(这就是为什么我们有PK或所谓的主键用于数据操作-只有一个值标识数据库表中的一个数据行)。
因此,对于编辑等操作或其他操作,无论如何我们都必须提取/获取/使用/拥有一行数据,如果该行不存在,那么代码将/应该/做/好主意/总是检查该行是否存在。
所以,在一天结束的时候,为什么按钮控件的“id”会很重要呢?反正它不会很重要,因为对于我放到gv中的每个按钮,我们都有一个按钮单击代码存根,而且我甚至不需要为gv事件费心。
但是,对于给定的按钮,您仍然可以自由地添加/use/have/enjoy/consider命令参数,并且您仍然可以基于命令参数传递来自一个gv行的值,但是在大多数情况下,这也不重要,因为所有数据库操作都基于数据库主键值。
但是,如果由于其他一些非常奇怪的原因(您没有与我们分享),您确实需要/希望获得被单击控件的“id”,那么当然您可以在上面的按钮单击事件中完成此操作:

Debug.Print("id of button click is = " & btn.ID)
Debug.Print("id of button click is = " & btn.ClientID)

因此,第一个将给予按钮id,第二个将给出为给定行单击生成的按钮id,因此输出如下:

id of button click is = cmdEdit
id of button click is = GridView1_cmdEdit_3

相关问题