Почему FindControl не может найти кнопку в нижнем колонтитуле моего ретранслятора?


Я использую событие OnItemDataBound, чтобы попытаться активировать отключенную кнопку в ретрансляторе. Проще говоря, если событие срабатывает, я знаю, что в ретрансляторе есть элементы, и поэтому хочу включить кнопку. Где я застрял, так это на приведении кнопки в функцию, чтобы я мог ее включить. Соответствующая часть кода ретранслятора приводится ниже:

<asp:Repeater ID="RptEnterHours" runat="server" DataSourceID="SQL_EmployeeGetTimesheet" ClientIDMode="Predictable" OnItemDataBound="RptEnterHours_Bound">
     '.....Irrelevant code.....
     <FooterTemplate>
          <asp:Button Enabled="false" ID="SubmitTimesheets" Text="Submit All Timesheets" OnClick="processTimesheetEntry" runat="server" OnClientClick="checkValues();" />&nbsp;
     </FooterTemplate>
</asp:Repeater>

Вот мой код:

Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)

    'Exposes the Submit All Timesheets button if timesheets are available.
    If (e.Item.ItemType = ListItemType.Item) Or _
        (e.Item.ItemType = ListItemType.AlternatingItem) Then
        Dim sButton As Button = TryCast(Me.FindControl("SubmitTimesheets"), Button)
        sButton.Enabled = True
    End If

End Sub

Эта и все другие попытки дали страшную " ссылку на объект, не заданную экземпляр сообщения объекта". Может ли кто-нибудь сказать мне, что я делаю неправильно и почему мой код не находит кнопку?

6 5

6 ответов:

Пожалуйста, попробуйте это, я уверен, что это поможет вам.

    If e.Item.ItemType = ListItemType.Footer Then
        Dim btn as new button
        btn = CType(e.Item.FindControl("SubmitTimesheets"), Button)
        btn.enabled = true
    End If

Вы ограничиваете его поиском внутри элемента и чередованием шаблонов элементов.

Измените это:

If (e.Item.ItemType = ListItemType.Item) Or _ 
        (e.Item.ItemType = ListItemType.AlternatingItem) Then 

Кому:

If (e.Item.ItemType = ListItemType.Footer) Then 

Вы хотите проверить для e.Item.ItemType = ListItemType.Нижняя сноска. Item и AlternatingItem используются для фактических записей данных, а не для нижнего колонтитула. Таким образом, кнопка действительно не существует для элементов и AlternatingItems.

Затем вы захотите добавить тест на наличие RptEnterHours.Объект DataSource имеет записи. Для этого вам нужно будет разыграть RptEnterHours.Источник данных для любого типа источника данных.

Итак, в основном что-то вроде этого. Вы, очевидно, нужно изменить его, чтобы он соответствовал вашему коду:

Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)

    'Exposes the Submit All Timesheets button if timesheets are available.
    If (e.Item.ItemType = ListItemType.Footer) Then
        Dim sButton As Button = TryCast(Me.FindControl("SubmitTimesheets"), Button)
        Dim myDataSource = CType(RptEnterHours.DataSource, MyDataSourceType)

        sButton.Enabled = (myDataSource.Count > 0)
    End If

End Sub

Прошло немного времени с тех пор, как я работал с веб-формами, но я считаю, что проблема состоит в двух аспектах.

Если тип элемента-Item или AlternatingItem, то вы знаете, что у вас есть данные в ретрансляторе. В этих случаях вы можете установить флаг уровня экземпляра, чтобы указать, что у вас есть элементы.

Затем, когда тип элемента-нижний колонтитул, и у вас есть элементы, которые вы хотите включить, чтобы нажать кнопку. Способ сделать это упоминается в неприемлемом ответе на вопрос, связанный с @ codingkiwi.com, но я ... поверьте, проблема заключается в контексте, в котором вы вызываете FindControl. Ты зовешь меня.FindControl, который будет искать дочерние элементы уровня 1 страницы (или пользовательский элемент управления, или элемент управления, или то, на что я ссылаюсь). Вы хотите искать дочерние элементы управления фактического элемента repeater, который в данном случае является нижним колонтитулом. Таким образом, поиск становится e.Item.FindControl.

Следует отметить, что, вероятно, существуют более элегантные способы определить, имеет ли управление ретранслятором элементы. Возможно, все, что вам нужно проверить в событии OnDataBound-это элемент нижнего колонтитула, а затем искать что-то вроде: (мой VB тоже может быть немного ржавым)

If (Me.RptEnterHours.Items IsNot Null AndAlso Me.RptEnterHours.Items.Any()) Then

Не уверен, почему он просто не включен в первую очередь, но это будет работать, так как он будет срабатывать для нижнего колонтитула после типа Item / AlternatingItem:

Private m_bolEnableButton As Boolean = False

Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)

    'Exposes the Submit All Timesheets button if timesheets are available. 
    If (e.Item.ItemType = ListItemType.Item) Or _
       (e.Item.ItemType = ListItemType.AlternatingItem) Then

        '"if the event is triggered, I know there are items in the repeater and therefore want to enable the button"
        m_bolEnableButton = True

    End If

    If e.Item.ItemType = ListItemType.Footer Then

        If m_bolEnableButton Then

            Dim sButton As Button = TryCast(e.Item.FindControl("SubmitTimesheets"), Button)
            sButton.Enabled = True

        End If

        m_bolEnableButton = False

    End If

End Sub

Причина, по которой вы получаете исключение Object null reference, заключается в том, что вы зациклены на приведении, которое не вызывает проблемы. Как правило, вы можете безопасно приводить результаты FindControl неявно. То, что вам нужно явно проверить, - это нулевая ссылка после того, как результаты FindControl будут захвачены.

Кроме того, вы должны искать ListItemType.Footer, чтобы вы могли ссылаться на строку нижнего колонтитула.

Наконец, функция FindControl () не является рекурсивной. Он находит элементы управления только в именовании верхнего уровня контейнер. В большинстве элементов управления databound каждая строка представляет свой собственный контейнер имен , поэтому вы должны найти элемент управления в строке, которую хотите найти. Когда вы используете Me, он ссылается на страницу. Вместо этого вы должны использовать e.Пункт.FindControl().

Код:

Dim bRecordsFound as Boolean = False

Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)
    If (e.Item.ItemType = ListItemType.Item) Or _
            (e.Item.ItemType = ListItemType.AlternatingItem) Then
        bRecordsFound = True
    End If
    If (e.Item.ItemType = ListItemType.Footer) And (bRecordsFound) Then
        Dim sButton As Button = e.Item.FindControl("SubmitTimesheets")
        If sButton IsNot Nothing Then
            sButton.Visible = True
        End If
    End If
End Sub