ASP.NET 2.0 中 GridView 嵌套 GridView






4.45/5 (51投票s)
2006年5月30日
6分钟阅读

639278

10607
一篇关于如何在 ASP.NET 2.0 中使用 GridView 控件的文章,其中包含模板内的多个控件。
引言
本文对于所有使用 ASP.NET 2.0 GridView
控件的用户都将非常有用。在这里,我将解释如何在 ASP.NET 2.0 中使用 GridView
控件,它比 ASP.NET 1.1 中的 DataGrid
控件更容易使用。我还将解释 GridView
和 DataGrid
控件之间的区别。我们还将探讨如何使用包含 DataGrid
的模板列。
背景
本文的基本思想是了解 ASP.NET 2.0 的 GridView
控件与 ASP.NET 1.1 中的 DataGrid
控件相比,在工作上有多么容易。我以前使用过 DataGrid
控件,我知道在同一项目中同时使用 GridView
控件有多么困难。使用 ASP.NET 2.0 GridView
控件非常容易,因为它非常用户友好。虽然我在使用它时遇到过很多困难,但我仍然可以说它比 DataGrid
控件好得多。GridView
控件内置了编辑、更新、删除、排序、选择和分页功能。
使用代码
在这个项目中,我使用了一个 ObjectDataSource
控件来将 GridView
绑定到数据源。这是 VS.NET 2005 中最好的功能之一。它非常容易使用。
DataGrid
和 GridView
控件的主要区别在于,DataGrid
控件具有集中的事件处理,这意味着 DataGrid
模板列内的任何控件引发的事件都将由 DataGrid
的 ItemCommand
事件处理。但 GridView
控件的此功能有所不同。它直接调用控件的处理程序。
我的意思是,在 GridView
控件中,如果您添加一个包含 GridView
的模板列,然后选择列排序命令,它不会调用主网格的任何事件,而是直接调用子网格的排序处理程序。这取决于用户如何利用此功能。
所以,我来解释一下代码。在这里,我有一个主表,它通过 MasterDataSouce
绑定到主网格,以及一个子表,它绑定到主网格模板列内的 GridView
。要将子网格绑定到 ChildDataSource
,我们必须使用 RowDataBound
事件,每次将数据库中的一行绑定到 GridView
行时都会调用该事件。
在这里,缓存的基本思想是,当需要单元格值时,您应该获取并显示它。所以在后台发生的事情是
主网格的 RowDataBound 事件
Protected Sub grdMaster_RowDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
Handles grdMaster.RowDataBound
Dim objListItem As DataControlRowState
objListItem = e.Row.RowState
Dim intMAsterID1 As Integer
If e.Row.RowType = DataControlRowType.DataRow Then
Dim grd As GridView
If objListItem = 5 Then
grd = CType(e.Row.FindControl("grdChildGridEdit"), GridView)
MasterTableID = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
intMAsterID1 = MasterTableID
ElseIf objListItem = DataControlRowState.Normal Or _
objListItem = DataControlRowState.Alternate Then
grd = CType(e.Row.FindControl("grdChildGridNormal"), GridView)
intMAsterID1 = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
Dim lnkButtton As LinkButton
lnkButtton = CType(e.Row.FindControl("Edit"), LinkButton)
If lnkButtton IsNot Nothing Then
lnkButtton.CommandName = "Edit Master"
lnkButtton.CommandArgument = intMAsterID1.ToString
End If
ElseIf objListItem = DataControlRowState.Edit Then
grd = CType(e.Row.FindControl("grdChildGridEdit"), GridView)
MasterTableID = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
intMAsterID1 = MasterTableID
End If
If grd IsNot Nothing Then
grd.DataSourceID = ""
grd.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = intMAsterID1
ChildDataSource.Select()
grd.DataBind()
End If
End If
End Sub
在这里,我所做的是,当主表行与 GridView
行绑定时,我找到 ChildGrid
控件,然后使用 MasterID
将该控件与 ChildDataSource
绑定。
当用户点击主网格的“编辑”按钮时,将使用上述代码。因此,在模板列中,带有编辑和删除选项的子网格将变得可见。现在,这个子网格的最大问题是,每个事件处理程序都必须手动编写,因为当任何命令被触发时,网格都会丢失其绑定。并且,与 DataGrid
不同的是,当子网格的任何命令(如编辑、删除、排序或分页)被触发时,子网格的处理程序都会被调用。在 DataGrid
中,无论内部控件是 DataGrid
、Button
还是 ListBox
,内部控件的事件都会首先由网格的 ItemCommand
事件处理。但在这里,它不会调用主网格的 RowCommand
事件,而是直接调用子网格的 RowCommand
事件。所以,事件流程如下:
- 当用户按下主网格中的“编辑”选项时,它将以“Edit”命令名调用主网格的
RowCommand
事件。 - 现在,它将在此处调用主网格的
RowDataBound
。您将找到特定行的RowState
是否为“Edit”,然后您将在模板列的EditTemplate
中找到带有编辑和删除命令的子网格。然后,您将网格绑定到ChildDataSource
。 - 现在,主网格看起来像下面这样
- 当您按下子网格的“编辑”选项时,它将调用子网格的
RowCommand
,就像DataGrid
调用主网格的ItemCommand
一样。它不会调用主网格的RowDataBound
,因此该行的子编辑网格不会绑定到数据源。所以您的网格会消失。现在,在子网格的RowCommand
中,您必须使用数据源重新绑定网格。grdchildgrid = CType(sender, GridView) If e.CommandArgument IsNot Nothing Then If IsNumeric(e.CommandArgument) Then intRowId = Convert.ToInt32(e.CommandArgument) End If End If If e.CommandName.Equals("Edit") Then grdchildgrid.DataSourceID = "" grdchildgrid.DataSource = ChildDataSource ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID ChildDataSource.Select() End If If e.CommandName.Equals("Update") Then UpdateChildRecord() grdchildgrid.DataSourceID = "" grdchildgrid.DataSource = ChildDataSource ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID ChildDataSource.Select() End If If e.CommandName.Equals("Delete") Then DeleteChildRecord() grdchildgrid.DataSourceID = "" grdchildgrid.DataSource = ChildDataSource ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID ChildDataSource.Select() End If If e.CommandName.Equals("Cancel") Then grdchildgrid.DataSourceID = "" grdchildgrid.DataSource = ChildDataSource ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID ChildDataSource.Select() End If If e.CommandName.Equals("Page") Then grdchildgrid.EditIndex = -1 grdchildgrid.DataSourceID = "" grdchildgrid.DataSource = ChildDataSource ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID ChildDataSource.Select() End If If e.CommandName.Equals("Sort") Then grdchildgrid.EditIndex = -1 Dim dt As DataView grdchildgrid.DataSourceID = "" ChildDataSource.SelectParameters(_ "MasterTableID").DefaultValue = MasterTableID dt = CType(ChildDataSource.Select(), DataView) If ViewState.Item("SortDirection") IsNot Nothing Then If CType(ViewState.Item("SortDirection"), _ SortDirection) = SortDirection.Ascending Then dt.Sort = e.CommandArgument & " ASC" ViewState.Item("SortDirection") = _ SortDirection.Descending Else dt.Sort = e.CommandArgument & " DESC" ViewState.Item("SortDirection") = _ SortDirection.Ascending End If End If grdchildgrid.DataSource = dt grdchildgrid.DataBind() End If
在这里,您会发现您必须为子网格手动处理每个命令,因为您不断更改子网格的绑定。我发现的另一件事是,如果您不为编辑、删除、更新、排序和分页命令编写处理程序,它将引发错误,因为当您按下子网格的编辑命令时,即使您在
RowCommand
事件中执行所有操作,它也会搜索子网格的RowEditing
处理程序。网格看起来像这样
- 在这里,重要的一点是,在子网格的
RowCommand
事件中,您将从网格的视图状态中获取网格中的旧值。但是,如果您不在RowCommand
事件中绑定子网格,子网格将不会绑定到任何数据源。 - 当您按下
UpdateCommand
时,它将调用RowCommand
,其CommandArgument
为“Update”。之后,它将调用子网格的RowUpdating
事件。但是e.NewValues
或e.OldValues
中将没有任何值。所以您必须在RowCommand
事件中执行更新。
关注点
ASP.NET 2.0 是一个非常好的框架。它是一个增强版本,非常方便使用。
历史
我将发布更多关于 ASP.NET 2.0 的有趣文章。如果您在使用 DataGrid
控件时遇到任何问题,请告诉我,我会尝试解决。