5,696,038 members and growing! (11,502 online)
Email Password   helpLost your password?
Web Development » ASP.NET Controls » General     Intermediate

A Master Detail DataGrid

By xicoloko

Implements a DataGrid with a Master/Detail view on data.
C#Windows, Win Mobile, .NET, .NET 1.0, .NET 1.1, Win2K, WinXP, Win2003, CE .NET 4.0, CE .NET 4.1, CE .NET 4.2, ASP.NET, Visual Studio, Dev

Posted: 7 May 2003
Updated: 7 May 2003
Views: 177,878
Bookmarked: 39 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
15 votes for this Article.
Popularity: 3.71 Rating: 3.16 out of 5
4 votes, 26.7%
1
1 vote, 6.7%
2
2 votes, 13.3%
3
2 votes, 13.3%
4
6 votes, 40.0%
5

Master Detail Grid

Introduction

Most of the examples that show a Master/Detail DataGrid do it using nested ListControls. This article shows how to accomplish the same using only a DataGrid-derived class.

Solution

The DataGrid shows exactly the number of rows that its DataSource has. Suppose you have the following need: show orders grouped by customers, but before a order from a new customer you show the customer details.

How can you do it?

Unfortunately there's no available/easy solution for it. You could create your own DataSource, manually adding the customer's details, and bind it to the grid. The solution I'll show is fairly easy to implement. All you have to do is to use the supplied DataGrid extended class and listen for the DataGridItemRender event. There you decide if you want to insert new rows into the DataGrid.Here's a code snippet of the provided sample project that adds customer information everytime the customerID of the order row changes:

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 };
    }
}

The way the MasterDetailGridhandles this event is fairly simple. Before the html is rendered the event is raised for each DataGridItem that the grid has. If new rows need to be added they are inserted in the grid's table. The rows collection which can be acessed using its Control property at index 0. Below is the code to accomplish it in the extended grid class:

///

/// 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);
}

You can have customize the html ouput even more using this approach. Currently it only handles new rows.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

xicoloko


XicoLoko is a brazilian developer based in Switzerland.

Occupation: Architect
Company: VisionOne AG
Location: Switzerland Switzerland

Other popular ASP.NET Controls articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 14 of 14 (Total in Forum: 14) (Refresh)FirstPrevNext
GeneralCheck out this article, it's an alternative. The approach is a litter different, but very simple. Plus, expand collapse is in client side.memberRajib Ahmed18:13 16 Sep '07  
GeneralDataGrid : add an eventmemberfriullano11:09 1 Dec '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 7 May 2003
Editor: Heath Stewart
Copyright 2003 by xicoloko
Everything else Copyright © CodeProject, 1999-2008
Web19 | Advertise on the Code Project