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

主从数据网格

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.52/5 (20投票s)

2003年5月8日

1分钟阅读

viewsIcon

261310

downloadIcon

3836

实现一个具有主/明细视图的 DataGrid。

Master Detail Grid

引言

大多数展示主/明细 DataGrid 的示例都是使用嵌套的 ListControls 来实现的。本文展示了如何仅使用 DataGrid 派生类来实现相同的功能。

解决方案

DataGrid 显示的行数与其 DataSource 中的行数完全一致。假设您有以下需求:按客户分组显示订单,但在新客户的订单之前显示客户详细信息。

您该如何实现?

不幸的是,没有可用的/简单的解决方案。您可以创建自己的 DataSource,手动添加客户的详细信息,然后将其绑定到网格。我将展示的解决方案实现起来比较简单。您所需要做的就是使用提供的 DataGrid 扩展类并侦听 DataGridItemRender 事件。在那里,您可以决定是否要在 DataGrid 中插入新行。以下是提供的示例项目中添加客户信息,每次订单行的 customerID 发生变化的代码片段:

private void grid_DataGridItemRender(object sender,
    CodeProject.MasterDetailGrid.DataGridItemRenderEventArgs e)
{
    DsCustomersOrders.OrdersRow order =
        this.dsCustomersOrders.Orders[e.ItemIndex];
    bool insertCustomerInfo = true;


    if (e.ItemIndex > 0)
    {
        DsCustomersOrders.OrdersRow previousOrder =
            this.dsCustomersOrders.Orders[e.ItemIndex - 1];
        insertCustomerInfo = previousOrder.CustomerID != order.CustomerID;
    }


    if (insertCustomerInfo)
    {
        //
        // Gets the customer information
        //
        DsCustomersOrders.CustomersRow customer = order.CustomersRow;


        //
        // Customer name
        //
        TableCell cellCustomerName = new TableCell();
        cellCustomerName.ColumnSpan = e.Grid.Columns.Count;
        cellCustomerName.Font.Bold = true;                
        
        cellCustomerName.Text = customer.CompanyName;
        cellCustomerName.HorizontalAlign = HorizontalAlign.Left;

        TableRow row1 = new TableRow();
        row1.BackColor = Color.Cyan;
        row1.Cells.Add(cellCustomerName);



        //
        // Customer Country
        //
        TableCell cellCustomerCountry = new TableCell();
        cellCustomerCountry.ColumnSpan = e.Grid.Columns.Count;
                
        cellCustomerCountry.Text = customer.Country;
        cellCustomerCountry.HorizontalAlign = HorizontalAlign.Right;

        TableRow row2 = new TableRow();
        row2.BackColor = row1.BackColor;
        row2.Cells.Add(cellCustomerCountry);

        e.NewRows = new TableRow[] { row1, row2 };
    }
}

MasterDetailGrid 处理此事件的方式非常简单。在渲染 html 之前,该事件会为网格拥有的每个 DataGridItem 触发。如果需要添加新行,它们将被插入到网格的表中。可以使用其 Control 属性在索引 0 处访问行集合。以下是在扩展的网格类中实现此功能的代码:

///
/// Renders the DataGrid content
///
protected override void RenderContents(HtmlTextWriter output) 
{
    if (HasControls()) 
    {
        Table table = this.Controls[0] as Table; 
        
        for (int i=0; i < table.Controls.Count; ++i) 
        {
            DataGridItem item = (DataGridItem)table.Controls[i]; 
            if (item.ItemType == ListItemType.AlternatingItem
                || item.ItemType == ListItemType.Item) 
            {
                DataGridItemRenderEventArgs args =
                    new DataGridItemRenderEventArgs(this, item.ItemIndex,
                        item.DataItem); 
                OnDataGridItemRender(args);
                
                //
                // if the user added a new row to the NewRows property
                //
                if (args.NewRows != null)
                {
                    foreach (TableRow row in args.NewRows)
                    {
                        table.Rows.AddAt(i, row);
                        ++i;
                    }
                }
            }
        }
    }

    base.RenderContents(output);
}

您可以使用这种方法进一步自定义 html 输出。目前它仅处理新行。

© . All rights reserved.