[asp.net] How to hide columns in an ASP.NET GridView with auto-generated columns?

GridView1.Columns.Count is always zero even SqlDataSource1.DataBind();

But Grid is ok

I can do

for (int i = 0; i < GridView1.HeaderRow.Cells.Count;i++)

I rename request headers here but

GridView1.Columns[i].Visible = false;

I can't use it because of GridView1.Columns.Count is 0.

So how can I hide them ?

This question is related to asp.net gridview

The answer is


Iterate through the GridView rows and make the cells of your target columns invisible. In this example I want to keeps columns 4-6 visible as is, so we skip those:

foreach (GridViewRow row in yourGridView.Rows)
   {
     for (int i = 0; i < rows.Cells.Count; i++)
     {
        switch (i)
        {
           case 4:
           case 5:
           case 6:
              continue;
        }
        row.Cells[i].Visible = false;
     };
   };

Then you will need to remove the column headers separately (keep in mind that removing header cells changes the length of the GridView after each removal):

grdReportRole.HeaderRow.Cells.RemoveAt(0);


I was having the same problem - need my GridView control's AutogenerateColumns to be 'true', due to it being bound by a SQL datasource, and thus I needed to hide some columns which must not be displayed in the GridView control.

The way to accomplish this is to add some code to your GridView's '_RowDataBound' event, such as this (let's assume your GridView's ID is = 'MyGridView'):

protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Cells[<index_of_cell>].Visible = false;
    }
}

That'll do the trick just fine ;-)


Try this to hide columns in an ASP.NET GridView with auto-generated columns, both RowDataBound/RowCreated work too.

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Or _
        e.Row.RowType = DataControlRowType.Header Then   // apply to datarow and header 

        e.Row.Cells(e.Row.Cells.Count - 1).Visible = False // last column
        e.Row.Cells(0).Visible = False  // first column

    End If
End Sub

Protected Sub GridView1_RowCreated(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowCreated

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

        e.Row.Cells(e.Row.Cells.Count - 1).Visible = False
        e.Row.Cells(0).Visible = False

    End If
End Sub

Similar to accepted answer but allows use of ColumnNames and binds to RowDataBound().

Dictionary<string, int> _headerIndiciesForAbcGridView = null;

protected void abcGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (_headerIndiciesForAbcGridView == null) // builds once per http request
    {
        int index = 0;
        _headerIndiciesForAbcGridView = ((Table)((GridView)sender).Controls[0]).Rows[0].Cells
            .Cast<TableCell>()
            .ToDictionary(c => c.Text, c => index++);
    }

    e.Row.Cells[_headerIndiciesForAbcGridView["theColumnName"]].Visible = false;
}

Not sure if it works with RowCreated().


Note: This solution only works if your GridView columns are known ahead of time.

It sounds like you're using a GridView with AutoGenerateColumns=true, which is the default. I recommend setting AutoGenerateColumns=false and adding the columns manually:

<asp:GridView runat="server" ID="MyGridView"
    AutoGenerateColumns="false" DataSourceID="MySqlDataSource">
    <Columns>
        <asp:BoundField DataField="Column1" />
        <asp:BoundField DataField="Column2" />
        <asp:BoundField DataField="Column3" />
    </Columns>
</asp:GridView>

And only include a BoundField for each field that you want to be displayed. This will give you the most flexibility in terms of how the data gets displayed.


You have to perform the GridView1.Columns[i].Visible = false; after the grid has been databound.


The Columns collection is only populated when AutoGenerateColumns=false, and you manually generate the columns yourself.

A nice work-around for this is to dynamically populate the Columns collection yourself, before setting the DataSource property and calling DataBind().

I have a function that manually adds the columns based on the contents of the DataTable that I want to display. Once I have done that (and then set the DataSource and called DataBind(), I can use the Columns collection and the Count value is correct, and I can turn the column visibility on and off as I initially wanted to.

static void AddColumnsToGridView(GridView gv, DataTable table)
{
    foreach (DataColumn column in table.Columns)
    {
        BoundField field = new BoundField();
        field.DataField = column.ColumnName;
        field.HeaderText = column.ColumnName;
        gv.Columns.Add(field);
    }
}

@nCdy: index_of_cell should be replaced by an integer, corresponding to the index number of the cell that you wish to hide in the .Cells collection.

For example, suppose that your GridView presents the following columns:

CONTACT NAME | CONTACT NUMBER | CUSTOMERID | ADDRESS LINE 1 | POST CODE

And you want the CUSTOMERID column not to be displayed. Since collections indexes are 0-based, your CUSTOMERID column's index is..........? That's right, 2!! Very good. Now... guess what you should put in there, to replace 'index_of_cell'??


I found Steve Hibbert's response to be very helpful. The problem the OP seemed to be describing is that of an AutoGeneratedColumns on a GridView.

In this instance you can set which columns will be "visible" and which will be hidden when you bind a data table in the code behind.

For example: A Gridview is on the page as follows.

<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" >
</asp:GridView>

And then in the code behind a PopulateGridView routine is called during the page load event.

protected void PopulateGridView()
{
    DataTable dt = GetDataSource();
    gv.DataSource = dt;
    foreach (DataColumn col in dt.Columns)
    {
        BoundField field = new BoundField();
        field.DataField = col.ColumnName;
        field.HeaderText = col.ColumnName;
        if (col.ColumnName.EndsWith("ID"))
        {
            field.Visible = false;
        }
        gv.Columns.Add(field);
    }
    gv.DataBind();
}

In the above the GridView AutoGenerateColumns is set to False and the codebehind is used to create the bound fields. One is obtaining the datasource as a datatable through one's own process which here I labeled GetDataSource(). Then one loops through the columns collection of the datatable. If the column name meets a given criteria, you can set the bound field visible property accordingly. Then you bind the data to the gridview. This is very similar to AutoGenerateColumns="True" but you get to have criteria for the columns. This approach is most useful when the criteria for hiding and un-hiding is based upon the column name.


As said by others, RowDataBound or RowCreated event should work but if you want to avoid events declaration and put the whole code just below DataBind function call, you can do the following:

GridView1.DataBind()
If GridView1.Rows.Count > 0 Then
    GridView1.HeaderRow.Cells(0).Visible = False
    For i As Integer = 0 To GridView1.Rows.Count - 1
        GridView1.Rows(i).Cells(0).Visible = False
    Next
End If

In the rowdatabound method for 2nd column

GridView gv = (sender as GridView);
gv.HeaderRow.Cells[2].Visible = false;
e.Row.Cells[2].Visible = false;