GridView嵌套GridView

      GridView嵌套可以显示当前选定的父记录组织同时显示所有子记录。例如,你可以用它创建一个完整的按类别组织的产品列表。下一个示例演示如何在单个网格中显示一个完整的分组产品列表,如下图所示:
      

      使用的基本技术是为附表创建一个GridView,它的每行又嵌入一个GridView,这些子GridView使用TemplateField来插入到父GridView中。唯一需要注意的是,不能在绑定父GridView的同时绑定子GridView,因为此时父行还没有被创建。相反,需要等待父GridView的DataBound时间发生。
      在这个示例中父GridView定义了两个列,它们都是TemplateField类型。第一个列组合了类别名称和类型
            
<asp:TemplateField HeaderText="Category">
                
                    
<ItemStyle  VerticalAlign="Top" Width="20%"></ItemStyle>
                    
<ItemTemplate>
                        
<br>
                        
<b>
                            
<%Eval("CategoryName"%>
                        
</b>
                        
<br>
                        
<br>
                        
<%Eval("Description" ) %>
                        
<br>
                    
</ItemTemplate>
                
</asp:TemplateField>

      第二个列包含嵌入的产品的GridView,它有两个绑定列。下面是略去相关样式特性后简要的代码:
      
    <asp:TemplateField HeaderText="Products">
                    
<ItemStyle VerticalAlign="Top"></ItemStyle>
                    
<ItemTemplate>
                        
<asp:GridView id="gridChild" runat="server" Font-Size="XX-Small" BackColor="White" AutoGenerateColumns="False"
                            CellPadding
="4" BorderColor="#CC9966" BorderWidth="1px" Width="100%" BorderStyle="None">
                    
                    
<RowStyle ForeColor="#330099" BackColor="White"></RowStyle>
                            
<HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
                                                            
                            
<Columns>
                                
<asp:BoundField DataField="ProductName" HeaderText="Product Name">
                                
<ItemStyle Width="250px" />
                                
</asp:BoundField>
                                
<asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" DataFormatString="{0:C}" />
                            
</Columns>        
                            
                        
</asp:GridView>
                    
</ItemTemplate>
                
</asp:TemplateField>

      注意第二个GridView的标记并没有设置DataSourceID属性。那是因为当父网格被绑定到它的数据源时,这些网格的数据源都通过编程来提供。
      现在创建两个数据源,一个用于获取产品类别,另一个用于获取特定类别的产品。第一个查询填充父GridView:     
 <asp:SqlDataSource ID="sourceCategories" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            ProviderName
="System.Data.SqlClient" SelectCommand="SELECT * FROM Categories"></asp:SqlDataSource>
 
      可以把第一个网格直接绑定到数据源:
      
<asp:GridView id="gridMaster" runat="server" GridLines="None" BorderWidth="1px" BorderColor="Tan"
            Font-Names
="Verdana" CellPadding="2" AutoGenerateColumns="False" BackColor="LightGoldenrodYellow"
            ForeColor
="Black" DataKeyNames="CategoryID" Font-Size="X-Small" DataSourceID="sourceCategories" OnRowDataBound="gridMaster_RowDataBound">

      这段代码非常典型,奥妙在于如何绑定子GridView。第二个数据源包含被多次调用以填充于GridView的查询。每次它获取不同类别中的产品。CategoryID作为一个参数被提供:
      
<asp:SqlDataSource ID="sourceProducts" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            ProviderName
="System.Data.SqlClient" SelectCommand="SELECT * FROM Products WHERE CategoryID=@CategoryID">
            
<SelectParameters>
                
<asp:Parameter Name="CategoryID" Type="Int32" />
            
</SelectParameters>
        
</asp:SqlDataSource>

      为了绑定子GridView,必须相应GridView.RowDataBound事件,它在每次行生成并绑定到父GridView时产生。此时,可以从第二列获取子GridView。并通过编程调用数据源的Select()方法把它绑定到产品信息。为了确保只显示当前类别的产品,还必须获取当前项的CategoryID字段并把它作为参数传递。代码如下:
      
protected void gridMaster_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        
// Look for GridView items.
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            
// Retrieve the GridView control in the second column.
            GridView gridChild = (GridView)e.Row.Cells[1].Controls[1];

            sourceProducts.SelectParameters[
0].DefaultValue = gridMaster.DataKeys[e.Row.DataItemIndex].Value.ToString();
            
object data = sourceProducts.Select(DataSourceSelectArguments.Empty);
            
            
// Bind the grid.
            gridChild.DataSource = data;
            gridChild.DataBind();
            

        }
    }
      
posted @ 2009-10-07 16:57  i'm zjz  阅读(4934)  评论(0编辑  收藏  举报