当然,当您重新加载页面并将整个网格重新加载到新的数据页面时,未绑定的复选框将不会保留或记住它的值。
这意味着您需要将复选框获取/抓取/保存到一些持续存在的集合中,然后在网格显示/重新加载时,您必须重新设置复选框。
换句话说,如果你跳转到一个新页面,那么你正在对页面和网格进行 100% 全新的重新加载 - 当然,一些旧的先前加载的网格将不记得选中了哪些复选框.
因此,您需要管理(保存)复选框。因此,唯一的问题就变成了我们是否在选中每个复选框或页面时执行此操作 - 实际上是我们需要在这里回答的唯一问题。
您没有提及您显示的行数 - 但给定页面的网格将持续存在(假设您正确编写了此内容并且在页面回发时不要重新加载网格。换句话说,您的页面加载事件仅在第一页加载时加载网格(PostBack = false)。假设这个关键的设计问题?(您编写的所有页面和每个页面都更好地遵循此规则!!!)。
好的,那么,我建议这样做:
这是标记:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" Width="50%" AllowPaging="True">
<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:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="ckSel" runat="server"
Checked='<%# MyChecked(Eval("ID")) %>'
AutoPostBack="true"
OnCheckedChanged="ckSel_CheckedChanged"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle CssClass="GridPager" />
</asp:GridView>
我们填充网格的代码是这样的:
Dim MyCheckList As New List(Of Integer)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
ViewState("CheckList") = MyCheckList
Else
MyCheckList = ViewState("CheckList")
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * from tblHotels ORDER BY HotelName", conn)
Dim rstData As New DataTable
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
Public Function MyChecked(ID As Integer) As Boolean
Return MyCheckList.Contains(ID)
End Function
现在我们如何将该“列表”保存到页面。
现在,为上面的复选框编写代码是一件简单的事情。
那个代码很简单,而且这个:
Protected Sub ckSel_CheckedChanged(sender As Object, e As EventArgs)
' user click on check box
Dim ckSel As CheckBox = sender
Dim gRow As GridViewRow = ckSel.Parent.Parent
Dim PKID As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
If ckSel.Checked Then
' add to our collection
MyCheckList.Add(PKID)
Else
' remove from check list
MyCheckList.Remove(PKID)
End If
End Sub
结果现在是这样的:
因此,现在 mylist 将维护并保留您所做选择的列表。
然后你可以说这样做:
' get selected data
Dim rstData As New DataTable
Dim strWhere As String = String.Join(",", MyCheckList.ToArray())
Dim strSQL As String
strSQL = "SELECT * from tblHotels WHERE ID IN(" & strWhere & ") ORDER BY HotelName"
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
' now do whatever,
For Each OneRow As DataRow In rstData.Rows
' do whatever
Next
这样你就可以传递 PK id 列表了。
注意在上面也要非常小心,我们没有显示,甚至必须显示每一行的 PK 值——我们为此使用了 DataKeys。这有很多原因,但重要的是我们不会在网格或标记中公开 PK 数据库 ID。出于安全原因,这非常好,这也意味着我们也没有在网格标记中包含 PK ID,我们甚至不必隐藏 pk 列 - 这就是 DataKeys 功能的用途。
编辑:公平地说?我确实使用了 Eval("ID") - 并且确实在 GV 中公开了 ID - 但实际上我不必这样做(代码更短)。