views:

10724

answers:

7

I have an ASP.NET GridView which has columns that look like this:

| Foo | Bar | Total1 | Total2 | Total3 |

Is it possible to create a header on two rows that looks like this?

|           |  Totals   |    
| Foo | Bar | 1 | 2 | 3 |

The data in each row will remain unchanged as this is just to pretty up the header and decrease the horizontal space that the grid takes up.

The entire GridView is sortable in case that matters. I don't intend for the added "Totals" spanning column to have any sort functionality.

Edit:

Based on one of the articles given below, I created a class which inherits from GridView and adds the second header row in.

namespace CustomControls
{
    public class TwoHeadedGridView : GridView
    {
        protected Table InnerTable
        {
            get
            {
                if (this.HasControls())
                {
                    return (Table)this.Controls[0];
                }

                return null;
            }
        }

        protected override void OnDataBound(EventArgs e)
        {
            base.OnDataBound(e);
            this.CreateSecondHeader();
        }

        private void CreateSecondHeader()
        {
            GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);

            TableCell left = new TableHeaderCell();
            left.ColumnSpan = 3;
            row.Cells.Add(left);

            TableCell totals = new TableHeaderCell();
            totals.ColumnSpan = this.Columns.Count - 3;
            totals.Text = "Totals";
            row.Cells.Add(totals);

            this.InnerTable.Rows.AddAt(0, row);
        }
    }
}

In case you are new to ASP.NET like I am, I should also point out that you need to:

1) Register your class by adding a line like this to your web form:

<%@ Register TagPrefix="foo" NameSpace="CustomControls" Assembly="__code"%>

2) Change asp:GridView in your previous markup to foo:TwoHeadedGridView. Don't forget the closing tag.

Another edit:

You can also do this without creating a custom class.

Simply add an event handler for the DataBound event of your grid like this:

protected void gvOrganisms_DataBound(object sender, EventArgs e)
{
    GridView grid = sender as GridView;

    if (grid != null)
    {
        GridViewRow row = new GridViewRow(0, -1,
            DataControlRowType.Header, DataControlRowState.Normal);

        TableCell left = new TableHeaderCell();
        left.ColumnSpan = 3;
        row.Cells.Add(left);

        TableCell totals = new TableHeaderCell();
        totals.ColumnSpan = grid.Columns.Count - 3;
        totals.Text = "Totals";
        row.Cells.Add(totals);

        Table t = grid.Controls[0] as Table;
        if (t != null)
        {
            t.Rows.AddAt(0, row);
        }
    }
}

The advantage of the custom control is that you can see the extra header row on the design view of your web form. The event handler method is a bit simpler, though.

+3  A: 

This article should point you in the right direction. You can programtically create the row and add it to the collection at position 0.

Mark Struzinski
Thanks! I used that link to come up with a solution.
Dana Robinson
A: 

You will have to create a class which extends gridview then override the CreateRow method.

try this as a starting point

Andrew Bullock
A: 

This is exactly what I was looking for. Thanks very much!

A: 

But when you save data,and if an error occurs on the server, misalignment of rows will occur

daniel
+1  A: 

Thanks for the updated question. You helped me do this:

alt text

Note for those who choose to use RowDataBound Method in VB.NET

If you end up with too many extra header rows popping up, add an If Statement that only proceeds if the gridview's header row is nothing (meaning it is the one currently being bound)

 If grid.HeaderRow Is Nothing Then

Thanks!

hamlin11
A: 

man but how can i add the second header at position [1], it won't let me do that, knowing that i'm using onRowCreated event.

hosam