39

How can I hide a TemplateField column in a GridView?

I tried the following:

<asp:TemplateField ShowHeader="False" Visible='<%# MyBoolProperty %>' >
<ItemTemplate>
    <asp:LinkButton ID="attachmentButton" runat="server" ... />
</ItemTemplate>

but it didn't work and gives the following error:

Databinding expressions are only supported on objects that have a DataBinding event. System.Web.UI.WebControls.TemplateField does not have a DataBinding event.

I tried also to hide it programmatically, but seems it's not possible to get a column by the name because there iss no name for TemplateField column.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Homam
  • 23,263
  • 32
  • 111
  • 187

9 Answers9

60
protected void OnRowCreated(object sender, GridViewRowEventArgs e)
{
         e.Row.Cells[columnIndex].Visible = false;
}


If you don't prefer hard-coded index, the only workaround I can suggest is to provide a HeaderText for the GridViewColumn and then find the column using that HeaderText.
protected void UsersGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
    ((DataControlField)UsersGrid.Columns
            .Cast<DataControlField>()
            .Where(fld => fld.HeaderText == "Email")
            .SingleOrDefault()).Visible = false;
}
naveen
  • 53,448
  • 46
  • 161
  • 251
10

If appears to me that rows where Visible is set to false won't be accessible, that they are removed from the DOM rather than hidden, so I also used the Display: None approach. In my case, I wanted to have a hidden column that contained the key of the Row. To me, this declarative approach is a little cleaner than some of the other approaches that use code.

<style>
   .HiddenCol{display:none;}                
</style>


 <%--ROW ID--%>
      <asp:TemplateField HeaderText="Row ID">
       <HeaderStyle CssClass="HiddenCol" />
       <ItemTemplate>
       <asp:Label ID="lblROW_ID" runat="server" Text='<%# Bind("ROW_ID") %>'></asp:Label>
       </ItemTemplate>
       <ItemStyle HorizontalAlign="Right" CssClass="HiddenCol" />
       <EditItemTemplate>
       <asp:TextBox ID="txtROW_ID" runat="server" Text='<%# Bind("ROW_ID") %>'></asp:TextBox>
       </EditItemTemplate>
       <FooterStyle CssClass="HiddenCol" />
      </asp:TemplateField>
Chad
  • 23,658
  • 51
  • 191
  • 321
10
For Each dcfColumn As DataControlField In gvGridview.Columns
    If dcfColumn.HeaderText = "ColumnHeaderText" Then
        dcfColumn.Visible = false                    
    End If
Next
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Deepak Mishra
  • 2,984
  • 1
  • 26
  • 32
7
GridView1.Columns[columnIndex].Visible = false;
Bugs
  • 4,491
  • 9
  • 32
  • 41
4

try this

.hiddencol
    {
        display:none;
    }
    .viscol
    {
        display:block;
    }

add following code on RowCreated Event of GridView

protected void OnRowCreated(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.DataRow)
     {
         e.Row.Cells[0].CssClass = "hiddencol";
     }
     else if (e.Row.RowType == DataControlRowType.Header)
     {
         e.Row.Cells[0].CssClass = "hiddencol";
     }
}
santosh singh
  • 27,666
  • 26
  • 83
  • 129
  • 3
    this is fine if all you care about is the visibility on the screen, however if you are showing/hiding private information (IE stackoverflow real name) then you cannot just hide it on the client, it can't be sent to the client at all – Nathan Koop Jul 30 '12 at 18:32
2

Am I missing something ?

If you can't set visibility on TemplateField then set it on its content

<asp:TemplateField>
  <ItemTemplate>
    <asp:LinkButton Visible='<%# MyBoolProperty %>' ID="foo" runat="server" ... />
  </ItemTemplate>
</asp:TemplateField> 

or if your content is complex then enclose it into a div and set visibility on the div

<asp:TemplateField>
  <ItemTemplate>
    <div runat="server" visible='<%# MyBoolProperty  %>' >
      <asp:LinkButton ID="attachmentButton" runat="server" ... />
    </div>
  </ItemTemplate>
</asp:TemplateField> 
frenchone
  • 1,547
  • 4
  • 19
  • 34
1
protected void gvLogMessageDetail_RowDataBound(object sender, GridViewRowEventArgs e)  
    { 
      if (e.Row.RowType == DataControlRowType.Header)   
        {  
            if (rdlForImportOrExport.SelectedIndex == 1)  
            {  
                e.Row.Cells[3].Visible = false;  
                e.Row.Cells[4].Visible = false;  
                e.Row.Cells[5].Visible = false;  
            }  
            else  
            {  
                e.Row.Cells[3].Visible = true;  
                e.Row.Cells[4].Visible = true;  
                e.Row.Cells[5].Visible = true;  
            }  
        }    
        if (e.Row.RowType == DataControlRowType.DataRow) //skip header row  
        {  
            try  
            {  
                if (rdlForImportOrExport.SelectedIndex == 1)  
                {  
                    e.Row.Cells[3].Visible = false;  
                    e.Row.Cells[4].Visible = false;  
                    e.Row.Cells[5].Visible = false;  
                }  
                else  
                {  
                    e.Row.Cells[3].Visible = true;  
                    e.Row.Cells[4].Visible = true;  
                    e.Row.Cells[5].Visible = true;  
                }  
                }  
            catch  
            {  
                ClientScript.RegisterStartupScript(GetType(), "Expand", "<SCRIPT   LANGUAGE='javascript'>alert('There is binding problem in child grid.');</script>");  
            }  
        }  
    }  
Anas Alweish
  • 2,818
  • 4
  • 30
  • 44
1

A slight improvement using column name, IMHO:

    Private Sub GridView1_Init(sender As Object, e As System.EventArgs) Handles GridView1.Init
    For Each dcf As DataControlField In GridView1.Columns
        Select Case dcf.HeaderText.ToUpper
            Case "CBSELECT"
                dcf.Visible = Me.CheckBoxVisible
                dcf.HeaderText = "<small>Select</small>"
        End Select
    Next
End Sub

This allows control over multiple column. I initially use a 'technical' column name, matching the control name within. This makes it obvious within the ASCX page that it's a control column. Then swap out the name as desired for presentation. If I spy the odd name in production, I know I skipped something. The "ToUpper" avoids case-issues.

Finally, this runs ONE time on any post instead of capturing the event during row-creation.

davidWazy
  • 61
  • 6
0

This can be another way to do it and validate nulls

DataControlField dataControlField = UsersGrid.Columns.Cast<DataControlField>().SingleOrDefault(x => x.HeaderText == "Email");
            if (dataControlField != null)
                dataControlField.Visible = false;
Juanito
  • 420
  • 1
  • 4
  • 18