views:

4607

answers:

3

Hi,

i'm trying to add a new headerrow to a Gridview. This row should appear below the original headerrow.

As far as I know I have two events to choose from:

1.) Gridview_RowDataBound 2.) Gridview_RowCreated

Option 1 is not an option as the grid is not binding the data on each postback. Option 2 does not work as expected. I can add the row, but it is added before the HeaderRow because the HeaderRow itself is not added yet in this event...

Please assist, thank you!

Code: (InnerTable property is exposed by custom gridview)

    Private Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
    If e.Row.RowType = DataControlRowType.Header Then
        Dim r As New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)

        For Each c As DataControlField In CType(sender, GridView).Columns
            Dim nc As New TableCell
            nc.Text = c.AccessibleHeaderText
            nc.BackColor = Drawing.Color.Cornsilk
            r.Cells.Add(nc)
        Next

        Dim t As Table = GridView1.InnerTable
        t.Controls.Add(r)
    End If
End Sub
A: 

Hi ropstah--

Try this when you add the row to the InnerTable:

t.Controls.AddAt(1, r)

Here's a quick basic test I did, which seems to work OK:

Protected Sub gridview_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridview.DataBound
    Dim g As GridView = CType(sender, GridView)

    Dim r As New GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal)
    Dim th As New TableHeaderCell()
    th.ColumnSpan = g.Columns.Count
    th.Text = "This is my new header"
    r.Cells.Add(th)

    Dim t As Table = CType(g.Controls(0), Table)
    t.Rows.AddAt(1, r)
End Sub
Jeremy Kratz
No this doesn't work, same issue as with option 1 in my initial question...
Ropstah
+1  A: 

Since this is a custom GridView, why don't you consider overriding the CreateChildControls method?

I.e (sorry, C#):

protected override void CreateChildControls()
{
 base.CreateChildControls();

 if (HeaderRow != null)
 {
  GridViewRow header = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
  for (int i = 0; i < Columns.Count; i++)
  {
   TableCell cell = new TableCell();
   cell.Text = Columns[i].AccessibleHeaderText;
   cell.ForeColor = System.Drawing.Color.Black;
   cell.BackColor = System.Drawing.Color.Cornsilk;
   header.Cells.Add(cell);
  }

  Table table = (Table)Controls[0];
  table.Rows.AddAt(1, header);
 }
}

UPDATE As was mentioned by Ropstah, the sniplet above does not work with pagination on. I moved the code to a PrepareControlHierarchy and now it works gracefully with pagination, selection, and sorting.

protected override void PrepareControlHierarchy()
{
 if (ShowHeader && HeaderRow != null)
 {
  GridViewRow header = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
  for (int i = 0; i < Columns.Count; i++)
  {
   TableCell cell = new TableCell();
   cell.Text = Columns[i].AccessibleHeaderText;
   cell.ForeColor = System.Drawing.Color.Black;
   cell.BackColor = System.Drawing.Color.Cornsilk;
   header.Cells.Add(cell);
  }

  Table table = (Table)Controls[0];
  table.Rows.AddAt(1, header);
 }

 //it seems that this call works at the beginning just as well
 //but I prefer it here, since base does some style manipulation on existing columns
 base.PrepareControlHierarchy();
}
Ruslan
Btw, this sniplet does work -- I tested.
Ruslan
I have to disagree, it seems to work at first, but when you enable paging / selecting you get unwanted results. 1.) Paging makes the row disappear.2.) Selecting makes the row appear again, but the cell contents are that of the first data row, not the accessible header texts...
Ropstah
You are right. I did not test w/pagination and selection. Good catch. It will be interesting to see where it should go.
Ruslan
Fixed. Now it works.
Ruslan
+1  A: 

Nice work guys, I used your technique for grouping my AJAX enabled gridview, and I searched for a long, long time. Cheers.

protected override void PrepareControlHierarchy()
{
    if (GroupColumns)
    {
        #region Group Column

        Table table = (Table)Controls[0];

        string lastValue = string.Empty;
        foreach (GridViewRow gvr in this.Rows)
        {
            string currentValue = gvr.Cells[GroupColumnIndex].Text;

            if (lastValue.CompareTo(currentValue) != 0)
            {
                // there's been a change in value in the sorted column
                int rowIndex = table.Rows.GetRowIndex(gvr);

                // Add a new sort header row
                GridViewRow sortRow = new GridViewRow(rowIndex, rowIndex, DataControlRowType.DataRow, DataControlRowState.Normal);

                TableCell sortCell = new TableCell();
                TableCell blankCell = new TableCell();

                sortCell.ColumnSpan = this.Columns.Count - 1;
                sortCell.Text = string.Format("{0}", currentValue);

                blankCell.CssClass = "group_header_row";
                sortCell.CssClass = "group_header_row";

                // Add sortCell to sortRow, and sortRow to gridTable
                sortRow.Cells.Add(blankCell);
                sortRow.Cells.Add(sortCell);
                table.Controls.AddAt(rowIndex, sortRow);

                // Update lastValue
                lastValue = currentValue;
            }
        }

        #endregion
    }

    HideColumns();

    base.PrepareControlHierarchy();
} 
djnava
thanks for sharing :)
Ropstah