我正在努力让数据网格对我来说很好地工作。我意识到可能还有其他控件可以完成我的计划,但我对数据网格很了解,所以想看看这是否可行。本质上我有以下绑定到 SQL 连接的数据网格:
<asp:datagrid ID="dginventory" AutoGenerateColumns="false" runat="server" Width="99.4%" AllowPaging="True" AllowSorting="true" PageSize="20" OnPageIndexChanged="ChangePage" OnSortCommand="SortGrid" OnEditCommand="dginventory_oneditcommand" OnDeleteCommand="dginventory_ondeletecommand" >
<HeaderStyle CssClass="datagridheader"/>
<AlternatingItemStyle CssClass="datagridalternating"/>
<ItemStyle cssClass="datagriditem"/>
<Columns>
<asp:BoundColumn DataField="PurchaseYear" ItemStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="center" HeaderText="YOP" ItemStyle-Width="4%" SortExpression="PurchaseYear ASC" />
<asp:BoundColumn DataField="PurchaseDate" ItemStyle-HorizontalAlign="Center" HeaderText="Purchased" ItemStyle-Width="7%" DataFormatString="{0:d}" SortExpression="PurchaseDate ASC" />
<asp:BoundColumn DataField="Number" HeaderText="Number" ItemStyle-Width="5%" SortExpression="Number ASC" />
<asp:BoundColumn DataField="Theme" HeaderText="Theme" ItemStyle-Width="10%" SortExpression="Theme ASC" />
<asp:BoundColumn DataField="Name" HeaderText="Name" ItemStyle-Width="30%" SortExpression="Name ASC" />
<asp:BoundColumn DataField="RRP" ItemStyle-HorizontalAlign="Left" HeaderText="RRP" ItemStyle-Width="4%" DataFormatString="{0:C}" />
<asp:BoundColumn DataField="PurchasePrice" ItemStyle-HorizontalAlign="Left" HeaderText="Cost" ItemStyle-Width="4%" DataFormatString="{0:C}" />
<asp:BoundColumn DataField="Discount" ItemStyle-HorizontalAlign="Left" HeaderText="Dis." ItemStyle-Width="4%" DataFormatString="{0:P1}" />
<asp:BoundColumn DataField="ReleaseDate" ItemStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="center" HeaderText="Rel. Date" ItemStyle-Width="7%" DataFormatString="{0:d}" SortExpression="ReleaseDate ASC" />
<asp:BoundColumn DataField="RetireDate" ItemStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="center" HeaderText="Ret. Date" ItemStyle-Width="7%" DataFormatString="{0:d}" SortExpression="RetireDate ASC" />
<asp:BoundColumn DataField="Retailer" HeaderText="Retailer" ItemStyle-Width="10%" SortExpression="Retailer ASC" />
<asp:BoundColumn DataField="StorageLocation" ItemStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="center" HeaderText="Box" ItemStyle-Width="3%" SortExpression="StorageLocation ASC" />
<asp:TemplateColumn HeaderText="" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="Middle" HeaderStyle-HorizontalAlign="center" ItemStyle-Width="2%">
<ItemTemplate>
<asp:ImageButton src="Images/edit-alt-regular-24.png" ID="btneditset" alt="Edit" class="imagebutton" CommandName="Edit" runat="server" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="Middle" HeaderStyle-HorizontalAlign="center" ItemStyle-Width="2%">
<ItemTemplate>
<asp:ImageButton src="Images/trash-regular-24.png" ID="btndeleteset" class="imagebutton" CommandName="Delete" runat="server"/>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
<PagerStyle NextPageText="Next -->" Font-Bold="True" PrevPageText="&lt-- Prev" HorizontalAlign="Center" ForeColor="White" BackColor="Red" Mode="NumericPages" />
</asp:datagrid>
如您所见,我有两个模板列,每个模板列都包含一个图像。一种用于删除,一种用于编辑。无论我如何尝试,我似乎都无法捕获这些图像按钮的点击事件。如果我用 ButtonColumn 替换其中之一,那么效果很好,但这意味着我无法使用图像。
在后面的代码中我设置了这些:
Sub dginventory_oneditcommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
lblfilters.Text = "edit"
End Sub
Sub dginventory_ondeletecommand(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
lblfilters.Text = "delete"
End Sub
他们似乎都没有真正抓住任何东西。我也尝试过使用 onitemcommand ,它似乎又没有触发。我也尝试向两个图像按钮添加 onclick,但同样没有乐趣。
希望我已经描述得足够好。我使用 vb.net 作为后面的代码,以防不清楚。
希望如此......
好的,当放入按钮、ImageButton,甚至是一行的组合框时,最简单的方法是什么?
忽略行命令方法,并为给定控件使用常规单击事件。
这里唯一的“技巧”是,因为控件是嵌套的(在转发器、Listview、GridView、DataGrid 等中),所以您没有给定控件的属性表,因此无法使用该属性控件上的工作表(或双击)以创建单击事件。
但是,您可以 100% 自由地通过直接输入标记来添加、使用和享受点击事件。 (英特尔感知仍然会帮助你)。
我还应该指出,DataGrid 可能是最古老的控件,事实上,您经常在工具箱中看不到 DataGrid。
所以,我建议大多数情况下使用 GridView。 (它们非常相似)。
如果您的数据“网格”有多个自定义控件,那么我建议使用 ListView,因为它对标记更加友好。不用担心,尽管 DataGrid 是一个较旧的控件,但使用它仍然可以。
那么,假设我们有一个像这样的简单 DataGrid:
(并注意 2 个图像按钮)。
所以,那么这个:
<asp:DataGrid ID="GHotels" runat="server" AutoGenerateColumns="false"
DataKeyField="ID" CssClass="table table-hover" Width="45%" >
<Columns>
<asp:BoundColumn HeaderText="First" DataField="FirstName" runat="server" />
<asp:BoundColumn HeaderText="Last" DataField="LastName" runat="server" />
<asp:BoundColumn HeaderText="City" DataField="City" runat="server" />
<asp:BoundColumn HeaderText="HotelName" DataField="HotelName" runat="server" />
<asp:BoundColumn HeaderText="Description" DataField="Description" runat="server" />
<asp:TemplateColumn HeaderText="Edit">
<ItemTemplate>
<asp:ImageButton ID="cmdEdit" runat="server"
ImageUrl="~/Content/edit2.png" Width="48"
/>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Delete">
<ItemTemplate>
<asp:ImageButton ID="cmdDelete" runat="server"
ImageUrl="~/Content/trashcan1.png" width="48"
OnClick="cmdDelete_Click"
/>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
加载网格的代码如下所示:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Dim strSQL As String =
"SELECT * FROM tblHotelsA
ORDER BY HotelName"
GHotels.DataSource = MyRst(strSQL)
GHotels.DataBind()
End Sub
结果是这样的:
好的,那么我们给上面的图片删除按钮添加一个删除点击事件。
所以,从编辑看来是这样的:
因此,如上所示,我们可以并且可以轻松地为给定的控件使用标准单击事件(或其他事件)。这意味着几乎没有理由去打扰和尝试使用 row 命令。额外的好处是,我们为每个控件都有一个单独的点击事件,并且它们不会全部被一堆 case 语句混入一个事件中。
在后面的代码中,我们可以像这样获取行信息:
Protected Sub cmdDelete_Click(sender As Object, e As ImageClickEventArgs)
Dim cmdDel As ImageButton = sender
Dim gRow As DataGridItem = cmdDel.NamingContainer
Dim PK As Integer = GHotels.DataKeys(gRow.ItemIndex)
Dim strSQL As String =
"DELETE FROM tblHotelsA WHERE ID = @ID"
Dim cmdSQL As New SqlCommand(strSQL)
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PK
' MyRstPE(cmdSQL)
Debug.Print($"Row index click = {gRow.ItemIndex}")
Debug.Print($"Database PK for row = {PK}")
End Sub
在上面,我展示了如何获取当前行(DataGridItem)。
上面我展示了如何获取数据库PK值。
在上面,我展示了如何获取行索引。
注意“命名”容器的使用。所有数据绑定控件都支持此功能,并返回当前行项目。
因此,当我单击给定的行按钮时,我会在输出/调试窗口中看到以下内容:
因此,您可以自由地对放置在 GridView、ListView、DataGrid 等中的控件使用常规单击事件。
上述建议还可以扩展到放入组合框或其他控件。也可以使用它们的事件,但您必须将事件设置直接“输入”到标记中,因为控件是嵌套的,因此没有可用的属性表。
为了完整起见,一遍又一遍地键入代码以使用提供的 SQL 提取数据表很快就会变得很累人,因此我在上面使用了一些辅助例程,并在整个应用程序中使用。
Public Function MyRst(strSQL As String, ByVal Optional strCon As String = "") As DataTable
If strCon = "" Then
strCon = My.Settings.TEST4
End If
Dim rstData As New DataTable
Using conn As New SqlConnection(strCon)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
rstData.TableName = strSQL
End Using
End Using
Return rstData
End Function
Public Function MyRstP(cmdSQL As SqlCommand, ByVal Optional strCon As String = "") As DataTable
If strCon = "" Then
strCon = My.Settings.TEST4
End If
Dim rstData As New DataTable
Using conn As New SqlConnection(strCon)
Using (cmdSQL)
cmdSQL.Connection = conn
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
Public Sub MyRstPE(cmdSQL As SqlCommand, ByVal Optional strCon As String = "")
If strCon = "" Then
strCon = My.Settings.TEST4
End If
Dim rstData As New DataTable
Using conn As New SqlConnection(strCon)
Using (cmdSQL)
cmdSQL.Connection = conn
conn.Open()
cmdSQL.ExecuteNonQuery()
End Using
End Using
End Sub