Link to home
Start Free TrialLog in
Avatar of ericlockshine
ericlockshineFlag for United States of America

asked on

Finding Template Column Controls in Header of GridView

Hi All,
I have a gridview that contains columns, and in each column is a template field.  In each template field is a <HeaderTemplate> and an <ItemTemplate>.  Inside the HeaderTemplate is a linkbutton object.

During Databinding (or before if possible), I want to hide certain columns from view based on permissions.  During page init, I get the permissions.

How do I find the link button control listed in the code snippet as HeaderLinkButton1?  How do I hide the entire column from view?  I still want to show the Username column regardless of permissions!

<asp:GridView runat="server" ID="GridView1" EnableMultipleSelect="true" AutoPostBack="true" AutoGenerateColumns="false" DataMemberUniqueID="itsID" DataSourceID="ObjectDataSource" OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
    <Columns>
        <asp:TemplateField>
            <HeaderTemplate>
                <asp:LinkButton ID="HeaderLinkButton1" runat="server" OnCommand="SortLinkButton_Command" CommandName="Sort" CommandArgument="Level" Text="Some Text" />
            </HeaderTemplate>
            <ItemTemplate>
                <%# GetLevel(Container.DataItem) %>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField>
            <HeaderTemplate>
                <asp:LinkButton ID="HeaderLinkButton2" runat="server" OnCommand="SortLinkButton_Command" CommandName="Sort" CommandArgument="Username" Text="User Name" />
            </HeaderTemplate>
            <ItemTemplate>
                <%# GetUsername(Container.DataItem) %>
            </ItemTemplate>
        </asp:TemplateField>
	</Columns>
</asp:GridView>

Open in new window

Avatar of samtran0331
samtran0331
Flag of United States of America image

Are you using a custom or 3rd party Gridview?
AutoPostBack, DataMemberUniqueID, and EnableMultipleSelect
are not properties of a default asp:Gridview....
Avatar of ericlockshine

ASKER

Custom Grid View.
with a standard gridview, you could hide the entire column with:
GridView1.Columns[0].Visible = False;

where/when (what event) would you want to find the control in the header?
This grid view just adds a paging control to the grid view.  It extends the stanard gridview.  It uses the AutoPostBack, DataMemberUniqueID and EnableMultipleSelect as additional fields only.
When the grid view gets its data, and before it is rendered, I want to hide certain columns based not on position, but on text in the gridview
I should explain a little further.  There are currently about 14 fields that I need to enable/disable based on priviledge.  At any point, someone other than me can move these columns around.  As a member of a team of about 10, I cannot just say GridView1.Columns[0].Visible = false.  What I need to be able to do is find the column that contains the link button that contains certain text (because the text is in a resource that is bound to the field).
Here is some code so far that I have been able to figure out.

What I don't know how to do is what to cast the HeaderTemplate as (It shows ITemplate as its base class).  If I knew what kind of object to cast this as, I could possibly find the linkbutton control that it has as a child control.

foreach (DataControlField dcf in GridView1.Columns) //loop through all the columns in the grid
{
    if (dcf is TemplateField) //because someone can put in any kind of control, the only ones I am interested in is the TemplateField controls
    {
        TemplateField tf = (TemplateField)dcf;
        tf.HeaderTemplate;
    }
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Velio
Velio
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
sorry, i was thinking of a datagrid.
Velio,
I was able to take your suggestion and use it partially.  I have found a GridView_RowDataBound event that takes something similar.  I was eventually able to determine the header control with my text I was looking for.  Thanks for your help!
Now I am stuck again....I have the DataControlFieldHeaderCell object and found the link button in the controls collection.  Now I want to hide the entire column, not just the header cell (which I can do).
How can I reference the entire column now to hide it?  check out the code below

        protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
			//GridView1 = GridView Control ID for the grid (from above)
            if (e.Row.RowType == DataControlRowType.Header)
            {
                bool isScanJob = true;
 
                //we have found the header row
                foreach (DataControlFieldHeaderCell dcfhc in e.Row.Cells)
                {
                    if (dcfhc.Controls.Count > 0)
                    {
						//loop through all the controls and find my linkbutton control;
                        foreach (Control ctl in dcfhc.Controls)
                        {
                            if (ctl is LinkButton)
                            {
								//found my link button control.  Hide the ENTIRE COLUMN if my LinkButton contains any of the text here.
                                LinkButton lb = (LinkButton)ctl;
                                if (!isScanJob)
                                {
                                    if ((lb.Text.Equals("Duration"))
                                        || (lb.Text.Equals("Highs"))
                                        || (lb.Text.Equals("Mediums"))
                                        || (lb.Text.Equals("Lows"))
                                        || (lb.Text.Equals("Warnings"))
                                        || (lb.Text.Equals("Informationals"))
                                        || (lb.Text.Equals("Score")))
                                    {
										//stuck here.  This will hide only the cell, not the entire column.
                                        dcfhc.Visible = false;
										//the next line will hide the row, not the column
										dcfhc.Parent.Visible = false;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

Open in new window

you can keep an index that you increment with each iteration of your foreach loop, this will give you the index of the column where you find the header cell... you can then use
GridView1.Columns[index].visible = false; when you want to hide it...

i haven't tested if this works, will do so as soon as i get the chance, but try it and let me know.
I actually found a better way!
dcfhc.ContainingControl.Visible = false;
This will set the entire column to an invisible status, while maintaining the column integrity.
Thanks Velio for the suggestion!  I now have the entire code working the way I want it.  I will post it here

Because you gave me the direction, I'm awarding you the points.  Thanks!

        protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.Header)
            {
                bool isScanJob = true;
                foreach (DataControlFieldHeaderCell dcfhc in e.Row.Cells)
                {
                    if (dcfhc.Controls.Count > 0)
                    {
                        foreach (Control ctl in dcfhc.Controls)
                        {
                            if (ctl is LinkButton)
                            {
                                LinkButton lb = (LinkButton)ctl;
                                if (!isScanJob)
                                {
                                    if ((lb.Text.Equals("Duration"))
                                        || (lb.Text.Equals("Highs"))
                                        || (lb.Text.Equals("Mediums"))
                                        || (lb.Text.Equals("Lows"))
                                        || (lb.Text.Equals("Warnings"))
                                        || (lb.Text.Equals("Informationals"))
                                        || (lb.Text.Equals("Score")))
                                    {
                                        dcfhc.ContainingField.Visible = false;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

Open in new window

It wasn't the OnItemDataBound event, it was the OnRowDataBound event that is part of the GridView.  I'm still giving you an A because it did point me in the right direction!  Thanks for the help!