views:

2836

answers:

2

I have a GridView...

<asp:GridView EnableViewState="true" 
                ID="grdResults" 
                runat="server" 
                CssClass="resultsGrid" 
                OnRowDataBound="grdResults_OnRowDataBound" 
                AutoGenerateColumns="false" 
                HeaderStyle-CssClass="header" 
                OnRowCommand="grdResults_OnRowCommand">
    <Columns>
       <asp:TemplateField>
           <ItemTemplate>
               <asp:Label ID="lblView" 
                           runat="server" 
                           Visible="false" 
                           Text="View">
               </asp:Label>
               <asp:HyperLink ID="hypEdit" 
                               runat="server" 
                               Visible="false" 
                               Text="(Edit)" 
                               CssClass="edit">
               </asp:HyperLink>
               <asp:LinkButton ID="btnDelete" 
                               runat="server" 
                               Visible="false" 
                               Text="(Delete)" 
                               CssClass="delete" 
                               CommandName="DeleteItem" 
                               OnClientClick="return confirm('Are you sure you want to delete?')">
               </asp:LinkButton>
               <asp:HyperLink ID="hypSelect" 
                               runat="server" 
                               Visible="false" 
                               Text="(Select)" 
                               CssClass="select">
               </asp:HyperLink>
           </ItemTemplate>
       </asp:TemplateField>
   </Columns>
</asp:GridView>

This has one static column containing a label two hyperlinks and a link button and also has a number of dynamically generated columns...

private void SetupColumnStructure(IEnumerable<string> columnNames)
{
    var columnNumber = 0;
    foreach (var columnName in columnNames)
    {
        var templateColumn = new TemplateField
                                 {
                                     ItemTemplate = new CellTemplate(columnName)
                                 };
       grdResults.Columns.Insert(columnNumber, templateColumn);
       columnNumber++;
    }
}

As part of the OnRowDataBound handler I retrieve one of the controls in the statically column and set some attributes on it...

protected void grdResults_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    .
    .
    .
    var row = e.Row;
    var rowData = row.DataItem as Dictionary<string, object>;
    if (rowData != null)
    {
       if ((bool)rowData[displayEditLink])
       {
           var hypEdit = (HyperLink)row.FindControl("hypEdit");
           hypEdit.NavigateUrl = "~/Pages/Edit.aspx?action=Edit&objectType=" + rowData[objectTypeLiteral] + "&id=" + rowData[objectIdLiteral];
           hypEdit.Visible = true;
       }
   }
   .
   .
   .
}

This all works fine but no column names are displayed. So I then modify the SetupColumnStructure method so that the HeaderText is set on the template field like this...

private void SetupColumnStructure(IEnumerable<string> columnNames)
{
    var columnNumber = 0;
    foreach (var columnName in columnNames)
    {
        var templateColumn = new TemplateField
                                 {
                                     ItemTemplate = new CellTemplate(columnName),
                                     HeaderText = columnName
                                };
       grdResults.Columns.Insert(columnNumber, templateColumn);
       columnNumber++;
    }
}

For some reason this one extra line change causes the row.FindControl("hypEdit"); call in the OnRowDataBound handler to return null.Can anyone see something im missing here or has anyone experienced a similar issue?

UPDATE

I've made sure that I'm not referring to a header or footer row here. Also, if I step over the object reference exception this occurs for every item that is in the DataSource.

Not sure if this helps, but as I expected, when I stepped through the code the table has generated all the columns expected but all cells (DataControlFieldCells) contain no controls when the HeaderText is set, yet all expected controls when it isnt set.

All very strange. Let me know if you can spot anything else.

A: 

When you added the HeaderText, a new RowType was added to the gridview. You'll need to check what type of row raised the OnRowDataBound event and take the appropriate action. In your case, just checking if the e.Row.RowType is a DataRow should solve your problem:

protected void grdResults_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
     if(e.Row.RowType == DataControlRowType.DataRow)
     {
          if ((bool)rowData[displayEditLink])
          {
           var hypEdit = (HyperLink)row.FindControl("hypEdit");
           hypEdit.NavigateUrl = "~/Pages/Edit.aspx?action=Edit&objectType=" + rowData[objectTypeLiteral] + "&id=" + rowData[objectIdLiteral];
           hypEdit.Visible = true;
          }
     }
}
Kevin W Lee
Thanks for your help but unfortunately this did not resolve the issue and I'm still looking for a solution :-/
Russell Giddings
A: 

Its because the control you are searching for is contained within another control. FindControl() does not look inside control collections of controls. You will need to write a recursiveFindControl() method.

Hope this helps a little!

Thanks for your help but unfortunately this did not resolve the issue and I'm still looking for a solution :-/
Russell Giddings