65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 2.0 中 GridView 嵌套 GridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (51投票s)

2006年5月30日

6分钟阅读

viewsIcon

639278

downloadIcon

10607

一篇关于如何在 ASP.NET 2.0 中使用 GridView 控件的文章,其中包含模板内的多个控件。

Master and Chid GridView In Normal Mode

引言

本文对于所有使用 ASP.NET 2.0 GridView 控件的用户都将非常有用。在这里,我将解释如何在 ASP.NET 2.0 中使用 GridView 控件,它比 ASP.NET 1.1 中的 DataGrid 控件更容易使用。我还将解释 GridViewDataGrid 控件之间的区别。我们还将探讨如何使用包含 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 中最好的功能之一。它非常容易使用。

DataGridGridView 控件的主要区别在于,DataGrid 控件具有集中的事件处理,这意味着 DataGrid 模板列内的任何控件引发的事件都将由 DataGridItemCommand 事件处理。但 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 中,无论内部控件是 DataGridButton 还是 ListBox,内部控件的事件都会首先由网格的 ItemCommand 事件处理。但在这里,它不会调用主网格的 RowCommand 事件,而是直接调用子网格的 RowCommand 事件。所以,事件流程如下:

  1. 当用户按下主网格中的“编辑”选项时,它将以“Edit”命令名调用主网格的 RowCommand 事件。
  2. 现在,它将在此处调用主网格的 RowDataBound。您将找到特定行的 RowState 是否为“Edit”,然后您将在模板列的 EditTemplate 中找到带有编辑和删除命令的子网格。然后,您将网格绑定到 ChildDataSource
  3. 现在,主网格看起来像下面这样

Master GridView in Edit Mode.

  1. 当您按下子网格的“编辑”选项时,它将调用子网格的 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 处理程序。

    网格看起来像这样

Master and Child GridView in Edit Mode.

  1. 在这里,重要的一点是,在子网格的 RowCommand 事件中,您将从网格的视图状态中获取网格中的旧值。但是,如果您不在 RowCommand 事件中绑定子网格,子网格将不会绑定到任何数据源。
  2. 当您按下 UpdateCommand 时,它将调用 RowCommand,其 CommandArgument 为“Update”。之后,它将调用子网格的 RowUpdating 事件。但是 e.NewValuese.OldValues 中将没有任何值。所以您必须在 RowCommand 事件中执行更新。

关注点

ASP.NET 2.0 是一个非常好的框架。它是一个增强版本,非常方便使用。

历史

我将发布更多关于 ASP.NET 2.0 的有趣文章。如果您在使用 DataGrid 控件时遇到任何问题,请告诉我,我会尝试解决。

© . All rights reserved.