GridView FindControl возвращает ноль, когда установлен HeaderText

У меня есть 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>

Это один статический столбец, содержащий метку, две гиперссылки и кнопку ссылки, а также ряд динамически генерируемых столбцов...

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++;
    }
}

Как часть обработчика OnRowDataBound я извлекаю один из элементов управления в статически столбце и устанавливаю некоторые атрибуты для него...

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;
       }
   }
   .
   .
   .
}

Это все работает нормально, но имена столбцов не отображаются. Затем я модифицирую метод SetupColumnStructure, чтобы HeaderText был установлен в поле шаблона следующим образом:

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++;
    }
}

По какой-то причине это одно дополнительное изменение строки вызывает row.FindControl("hypEdit"); вызовите обработчик OnRowDataBound, чтобы вернуть null. Может кто-нибудь увидеть что-то, что мне здесь не хватает, или кто-нибудь сталкивался с подобной проблемой?

ОБНОВИТЬ

Я удостоверился, что я не имею в виду строку верхнего или нижнего колонтитула здесь. Кроме того, если я перехожу через исключение ссылки на объект, это происходит для каждого элемента в источнике данных.

Не уверен, что это поможет, но, как я и ожидал, когда я прошел через код, таблица сгенерировала все ожидаемые столбцы, но все ячейки (DataControlFieldCells) не содержат элементов управления, когда установлен HeaderText, но все ожидаемые элементы управления, когда он не установлен.

Все очень странно. Дайте мне знать, если вы можете найти что-нибудь еще.

2 ответа

Это потому, что искомый элемент управления содержится в другом элементе управления. FindControl() не просматривает наборы элементов управления. Вам нужно будет написать метод recursiveFindControl().

Надеюсь, это немного поможет!

Когда вы добавили HeaderText, новый RowType был добавлен в сетку. Вам нужно проверить, какой тип строки вызвал событие OnRowDataBound, и предпринять соответствующее действие. В вашем случае, просто проверка, является ли e.Row.RowType типом DataRow, должна решить вашу проблему:

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;
          }
     }
}
Другие вопросы по тегам