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

可编辑的嵌套 GridView(一体化)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (111投票s)

2007年8月16日

CPOL

5分钟阅读

viewsIcon

616432

downloadIcon

20616

如何在 ASP.NET 中使用 C# 创建一个一体化的可编辑嵌套 GridView。

Screenshot - EditNestedGridView.jpg

引言

本文解释了如何创建一个 ASP.NET 可编辑嵌套 GridView。在这里,我将解释如何为 GridView 提供编辑/添加/删除/更新/分页/排序的所有功能,并且不仅仅是一个 GridView,我还将解释如何将这些功能扩展到嵌套的 Grid (GridView 中套 GridView)。我提供了功能齐全的源代码,它们是自解释的。

背景

之前的文章解释了嵌套可编辑 DataGrids 的功能。本文提供了 GridView (Visual Studio 2005, .NET 2.0) 中的所有这些功能。通过 GridView 和 DataSource 控件的组合,创建可编辑的 GridView 非常容易。

Using the Code

这是一个名为 EditNestedGridView 的虚拟目录的 Web 应用程序。您可以创建相同的虚拟目录来运行此应用程序,或者创建任何其他虚拟目录并映射到此目录的路径,以便从浏览器访问它。由于我使用的是 Access 2003 作为我的数据库,因此您需要在计算机上安装 Microsoft Access。我修改并使用了 NorthWind 数据库。我已将其包含在名为 App_Data 文件夹的代码包中。我使用 C# 进行代码隐藏文件。在 Visual Studio 2005 中,选择 File --> Open --> Web Site,然后导航到 EditNestedGridView 文件夹。

分步过程

随附的代码是自解释的,但我会尽量详细解释。

  1. 由于我将使用 DataSource 控件,因此我们首先创建一个 AccessDataSource 控件,如下所示:
  2. <asp:AccessDataSource ID="AccessDataSource1" runat="server" 
        DataFile="App_Data/Northwind.mdb" 
        SelectCommand="SELECT [Customers].[CustomerID], 
        [Customers].[CompanyName],[Customers].[ContactName],
        [Customers].[ContactTitle],[Customers].[Address] FROM [Customers] 
        ORDER BY [Customers].[CustomerID]"></asp:AccessDataSource>

    DataSource 控件的主要优势在于,它简化了检索和绑定数据,甚至进行排序、分页或编辑数据所需的自定义代码量。

  3. 现在,让我们创建一个简单的 GridView 控件,并将其连接到先前创建的 DataSource 控件,如下所示:
  4. <asp:GridView ID="GridView1" AllowPaging="True" BackColor="#f1f1f1" 
                AutoGenerateColumns=false DataSourceID="AccessDataSource1" 
                DataKeyNames="CustomerID"
                style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 32px" 
                ShowFooter=true Font-Size=Small
                Font-Names="Verdana" runat="server" GridLines=None BorderStyle=Outset>

    GridView 非常类似于 DataGrid,它拥有 DataGrid 的所有列功能,例如 TemplateColumnBoundColumn,用于将数据作为列填充。EditItemTemplateFooterTemplate 可用于编辑和添加目的。以下代码显示了父 Grid 的列:

    <asp:TemplateField HeaderText="Customer ID" SortExpression="CustomerID">
        <ItemTemplate>
            <asp:Label ID="lblCustomerID" Text='<%# Eval("CustomerID") %>' 
                runat="server"></asp:Label>
        </ItemTemplate>
        <EditItemTemplate>
            <asp:Label ID="lblCustomerID" Text='<%# Eval("CustomerID") %>' 
                runat="server"></asp:Label>
        </EditItemTemplate>
        <FooterTemplate>
            <asp:TextBox ID="txtCustomerID" Text='' runat="server"></asp:TextBox>
        </FooterTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Company Name" SortExpression="CompanyName">
        <ItemTemplate><%# Eval("CompanyName") %></ItemTemplate>
        <EditItemTemplate>
            <asp:TextBox ID="txtCompanyName" Text='<%# Eval("CompanyName") %>' 
                runat="server"></asp:TextBox>
        </EditItemTemplate>
        <FooterTemplate>
            <asp:TextBox ID="txtCompanyName" Text='' runat="server"></asp:TextBox>
        </FooterTemplate>
    </asp:TemplateField>
    ..........................
    ..........................
    
    <asp:CommandField HeaderText="Edit" ShowEditButton="True" />
    <asp:TemplateField HeaderText="Delete">
        <ItemTemplate>
            <asp:LinkButton ID="linkDeleteCust" CommandName="Delete" 
                runat="server">Delete</asp:LinkButton>
        </ItemTemplate>
        <FooterTemplate>
            <asp:LinkButton ID="linkAddCust" CommandName="AddCustomer" 
                runat="server">Add</asp:LinkButton>
        </FooterTemplate>
    </asp:TemplateField>

    现在我们已经有了所有的列,我们需要事件处理程序来处理添加/编辑/删除操作。处理这些事件比处理 DataGrid 的事件要简单得多。DataSource 控件负责分页和排序操作。这是包含所有这些事件的最终父 GridView 控件:

    <asp:GridView ID="GridView1" AllowPaging="True" BackColor="#f1f1f1" 
                AutoGenerateColumns=false DataSourceID="AccessDataSource1" 
                DataKeyNames="CustomerID"
                style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 32px" 
                ShowFooter=true Font-Size=Small
                Font-Names="Verdana" runat="server" GridLines=None 
                OnRowDataBound="GridView1_RowDataBound" 
                OnRowCommand = "GridView1_RowCommand" 
                OnRowUpdating = "GridView1_RowUpdating" BorderStyle=Outset
                OnRowDeleting = "GridView1_RowDeleting" 
                OnRowDeleted = "GridView1_RowDeleted"
                OnRowUpdated = "GridView1_RowUpdated" AllowSorting=true>

    有了以上所有选项,GridView 的外观如下:

    Screenshot - EditNestedGridView1.jpg

  5. 到目前为止,我们已经创建了一个父 GridView。现在我们将把这些功能也扩展到子 GridView
  6. 在添加另一个 GridView 之前,我们必须了解 GridView 如何将其内容作为 HTML 标签发出。对于 Internet Explorer 浏览器,GridView 就像一个普通的 Table,带有 TRTD 标签。因此,如果我们能操纵父 GridView 来强制关闭一个行并将其子 GridView 作为另一行发出,我们就完成了。

    显示的是一些 HTML 表格单元格和行标签,它们有效地拦截了 GridView 当前将生成的输出,并用我们自己的特殊实现替换。也就是说,我们在表格绘制时告诉表格关闭当前单元格、当前行,然后添加一个带有单个空白列(用于间距)的新行,以及另一个跨越所有列的列,我们将使用它来显示第二个 GridView。以下是解释此代码片段:

    <asp:TemplateField>
        <ItemTemplate>
            <tr>
            <td colspan="100%">
            <div id="div<%# Eval("CustomerID") %>" 
                style="display:none;position:relative;left:15px;OVERFLOW: auto;WIDTH:97%" >

    在这里,我创建了一个 ID 为 div Eval("CustomerID") 的 div,其 ID 为 Customer (父行),它保存子 GridView,以便我们可以使用 DIV ID 动态地隐藏和展开它。此外,我们需要主 GridView 中的一列来保存用于展开和折叠子 GridView 的图像,如下所示:

    <asp:TemplateField>
        <ItemTemplate>
            <a href="javascript:expandcollapse('div<%# Eval("CustomerID") %>', 'one');">

    在这里,JavaScript 函数 expandcollapse 将负责展开和折叠操作。

  7. 为了绑定子 GridView,我们不能像用于父 GridView 那样使用静态 DataSource 控件。我们将不得不根据相应父行的客户 ID 动态准备查询,这可以在父 Grid 的 RowDataBound 事件中完成,如下所示:

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        GridViewRow row = e.Row;
        string strSort = string.Empty;
    
        // Make sure we aren't in header/footer rows
        if (row.DataItem == null)
        {
            return;
        }
    
        //Find Child GridView control
        GridView gv = new GridView();
        gv = (GridView)row.FindControl("GridView2");
    
        //Prepare the query for Child GridView by passing 
        //the Customer ID of the parent row
        gv.DataSource = 
            ChildDataSource(((DataRowView)e.Row.DataItem)["CustomerID"].ToString(), 
            strSort);
        gv.DataBind();
    }

    在这里,ChildDataSource 函数使用传递的客户 ID 构建查询并返回 AccessDataSource

  8. 现在,我们也有了子 Grid 中的数据,并且可以动态展开和折叠。让我们像对待父 Grid 一样逐个添加效果。但是,在进一步操作之前,有一个棘手的部分。对于父 Grid,只有一个唯一的 ID (GridView1),而对于子 Grid,将有多个在运行时生成的唯一 ID。如果我们能识别出我们需要的那个,就可以解决这个问题。

    在父 Grid 的情况下,分页和排序由 DataSource 控件处理。对于子 Grid,我们必须手动处理它,使用相应的事件 PageIndexChangingSorting。分页事件的示例代码如下:

    protected void GridView2_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        GridView gvTemp = (GridView)sender;
        gvUniqueID = gvTemp.UniqueID;
        gvNewPageIndex = e.NewPageIndex;
        GridView1.DataBind();
    }

    在这里,我们识别了需要分页的子 Grid 的运行时唯一 ID 以及新页码。我们将在父 Grid 的 RowDataBound 事件中使用这些变量值,如下所示:

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        ........................
        //Find Child GridView control
        GridView gv = new GridView();
        gv = (GridView)row.FindControl("GridView2");
        //Check if any additional conditions (Paging, Sorting, Editing, etc) 
        //to be applied on child GridView
        if (gv.UniqueID == gvUniqueID)
        {
            gv.PageIndex = gvNewPageIndex;
            gv.EditIndex = gvEditIndex;
            //Check if Sorting used
            if (gvSortExpr != string.Empty)
            {
                GetSortDirection();
                strSort = " ORDER BY " + string.Format("{0} {1}", gvSortExpr, gvSortDir);
            }
            //Expand the Child grid
            ClientScript.RegisterStartupScript(GetType(), "Expand", 
                "<script language="javascript"></script>");
        }
        ..........................
    }

其余操作 (排序/编辑/更新/删除) 也可以类似分页的方式处理。请参阅上面附加的源代码。

结论

GridViewDataGrid 拥有更多的功能,这使得编码更加容易,而且我们可以在中间包含 HTML 标签以获得更大的灵活性。

© . All rights reserved.