Friday, April 15, 2011

Add Gridview Row AFTER Header

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
From stackoverflow
  • 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
    
    Ropstah : No this doesn't work, same issue as with option 1 in my initial question...
  • 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.
    Ropstah : 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...
    Ruslan : 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.
  • 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();
    } 
    
    Ropstah : thanks for sharing :)

0 comments:

Post a Comment