Ed Giardina's .NET Blog

Blogging about Hobbyist Adventures in C#, XNA, ASP.NET and other stuff

What? No Columns in my GridView?


Well, lesson learned. the GridView is not infalliable.

So I am building another nightmare report that will sift through reams of data. This one has two Gridviews, one nested inside of the other. The point of the Gridview will be to display an asset and have the child gridview's rows display the locations where the asset exists. Aside from the entire table being a Pivot/Crosstab, and that I have to expect, on minimum, 100 assets to be returned for any search, I am also working with a custom data layer written for the project. So binding to these grids is, well, challenging.

To keep the amount of database traffic down, I only make two queries: One to get the asset list, and one to get all locations for those assets. Storing the locations in a datatable, I can use the datatable's 'Select' method to populate the subgrid. One problem we have is that the key field we 'Select' on, the ID of the asset, is already listed in the parent table, so I want to hide it.

    <asp:TemplateField>
        <ItemTemplate>
            <td>&nbsp;<td colspan="5">
            </asp:GridView runat="server" ID="SubViewContainer" CssClass="Grid"/>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>



Here is the nested grid, inside a template field in the parent grid. On the RowDataBound event of the parent grid, I bind the child grid by extracting the control from the parent grid's columns. With the grid extracted, I can bind it individually.

GridView SubView = (GridView)e.Row.Cells[6].Controls[1];
DataRow[] SubData = WeeklySubData.Tables[0].Select("ID = '" + ID + "'");
DataTable Tbl = WeeklySubData.Tables[0].Clone();

foreach (DataRow D in SubData)
{
    Tbl.ImportRow(D);
}
SubView.DataSource = Tbl;
SubView.DataBind();


So this gets us our sub-data bound to the sub-grid. Great! Now let's hide the first column. That first column is only there so we can use the Select method, we don't need to display it. So let's just do
SubView.Columns[0].visible = false;
, right?

Actually, no. For some reason, I don't have access to the Columns and that line would throw a runtime exception. The columns will have a Count of 0 and I can't do anything. So what's the solution?

Eventually I broke down and added an event handler to handle the 'OnRowCreated' event of the sub-grid. When this event fires, we're able to see the row we're in and hide the first cell of that row. I'm sure this is probably more expensive performance-wise; but it also works, which is the primary feature.

The event handler attachment code looks like 

SubView.RowCreated += new GridViewRowEventHandler(SubView_RowCreated);

And the event handler looks like:

void SubView_RowCreated(object sender, GridViewRowEventArgs e)
{
    e.Row.Cells[0].Visible = false;
}


Problem solved. now to explain to my boss what I've been doing all morning.

Comments

Flesh said:

Tnx for this info! it was wery useful to me :)

# May 22, 2007 11:51 PM

aspNET said:

Hi Ed, this really works but only if the gridview doesn't allow paging. If the gridview has more records than its' PageSize, the Pager disappears.

I have yet to find a solution for this, any ideas?

Thanks

# May 23, 2007 9:22 PM

virender thakur (spain madrid ) said:

protected void GridViewPP_USUARIOS_IDENTIDAD_RowDataBound(object sender, GridViewRowEventArgs e)

       {

           e.Row.Cells[1].Visible = false;

       }

***************************************************

error error this code is working for

e.Row.Cells[0].Visible = false; but not for

e.Row.Cells[1].Visible = false;...????? why i am getting follwing error

************************************************

Exception Details: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.

Parameter name: index

Source Error:

Line 408:        protected void GridViewPP_USUARIOS_IDENTIDAD_RowDataBound(object sender, GridViewRowEventArgs e)

Line 409:        {

Line 410:            e.Row.Cells[1].Visible = false;

Line 411:        }

Line 412:    }

# May 31, 2007 10:28 AM

virender thakur (spain madrid ) said:

e.Row.Cells[1].Visible = false;

how to do paging with this code

# May 31, 2007 10:44 AM

virender thakur (spain madrid ) said:

*******for answer of your question aspNET ***********

protected void GridViewPP_USUARIOS_IDENTIDAD_RowCreated(object sender, GridViewRowEventArgs e)

       {

           if (e.Row.RowType == DataControlRowType.DataRow)

           {

               e.Row.Cells[1].Visible= false;

           }

           else if (e.Row.RowType == DataControlRowType.Header)

           {

               e.Row.Cells[1].Visible= false;

           }

       }

# May 31, 2007 11:09 AM

virender thakur (spain madrid ) said:

protected void GridViewPP_USUARIOS_IDENTIDAD_RowCreated(object sender, GridViewRowEventArgs e)

       {

           if (e.Row.RowType == DataControlRowType.DataRow)

           {

               e.Row.Cells[1].Visible= false;

           }

           else if (e.Row.RowType == DataControlRowType.Header)

           {

               e.Row.Cells[1].Visible= false;

           }

       }

# May 31, 2007 11:10 AM

Mamta said:

I have used your code. Its working

protected void GridViewPP_USUARIOS_IDENTIDAD_RowCreated(object sender, GridViewRowEventArgs e)

      {

          if (e.Row.RowType == DataControlRowType.DataRow)

          {

              e.Row.Cells[1].Visible= false;

          }

          else if (e.Row.RowType == DataControlRowType.Header)

          {

              e.Row.Cells[1].Visible= false;

          }

      }

Thanks virender

# August 24, 2007 11:17 AM

Marta said:

Thanks :)

# December 19, 2007 11:27 AM

RajaSekhara karumuru said:

Good Solution by Ed.

I used another solution without using RowCommand and thought of sharing it here.

//make it visible before binding.if not we are not going to get this column value in remaining event handler methods

SubView.columns[1].visible=true;

SubView.DataSource = Tbl;

SubView.DataBind();

SubView.columns[1].visible=false;

Thanks

RajaSekhara karumuru

# January 22, 2008 7:33 PM

Awanish said:

i want to show subgrid in gridview,problem is that on each row left it should be group of record,when click on + sign all record associated will come under,

thanks in advance

# February 7, 2008 7:19 AM

yash said:

Thanks virender!!!!

# April 19, 2008 9:28 AM

Renee said:

Here is the code that helped me in VB.NET based on virender's code. It works because when you hide every row, you also hide the pager control in the bottom row - so if you want to allowpaging, you have to make sure that row of the gridview is displayed, so you only hide header & data rows.

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound

If e.Row.RowType = DataControlRowType.DataRow Or e.Row.RowType = DataControlRowType.EmptyDataRow Or e.Row.RowType = DataControlRowType.Header Then

           'hide the cells in the following fields if this is a datarow, emptydatarow, or header in the gridview

           e.Row.Cells(1).Visible = False

           e.Row.Cells(4).Visible = False

End If

end sub

# May 2, 2008 5:41 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)