5

I am using an OnItemDataBound event to attempt to activate a disabled button in a repeater. Quite simply, if the event is triggered, I know there are items in the repeater and therefore want to enable the button. Where I am getting stuck is on casting the button in the function so I can enable it. The relevant part of the repeater code is below:

<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>

This is my code behind:

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

This and all other attempts has yielded the dreaded "Object reference not set to an instance of an object" message. Can anyone tell me what I am doing wrong and why my code behind won't find the button?

Ryan
  • 253
  • 3
  • 17

6 Answers6

3

please try this i am sure it will help you.

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

You're restricting it to looking within the item and alternating item templates.

Change this:

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

To:

If (e.Item.ItemType = ListItemType.Footer) Then 
Fiona - myaccessible.website
  • 14,481
  • 16
  • 82
  • 117
0

You want to test for e.Item.ItemType = ListItemType.Footer. Item and AlternatingItem are used for the actual data records, not the footer. Therefore, the button indeed does not exist for Items and AlternatingItems.

Then, you will want to add a test for whether the RptEnterHours.DataSource object has records. For this, you will need to cast the RptEnterHours.DataSource to whatever type the data source is.

So, basically something like this. You will obviously need to change it to fit your code:

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
DCNYAM
  • 11,966
  • 8
  • 53
  • 70
  • I think there may be some confusion. The existence of the footer button is not the criteria. The existence of an Item or AlternatingItem are the criteria for determining whether or not I will enable the button in the footer. I am pretty confident, therefore, that my error is in the casting of the button, not the IF statement. Please feel free to correct me if I am misunderstanding your objective. – Ryan Aug 22 '12 at 20:11
  • @Ryan This event is raised for each "item", including the header, footer, and individual data items. The problem is that the footer is the only section that contains the button. Therefore, if you try to cast the button while your in this event for a regular item, you will get a NullReferenceException because the button does not exist for that item. You need to check that you are in the footer. Then, you need to check the data source of the control and enable/disable the button based on whether there are items in the data source. You could also check if there are RptEnterHours.Items. – DCNYAM Aug 23 '12 at 14:32
0

It's been a little while since I've worked with web forms, but I believe the problem is two fold.

When the item type is Item or AlternatingItem then you know you have data in the repeater. In those cases you could set an instance level flag to indicate that you have items.

Then, when the item type is footer AND you have items you want to enable to button. The way to do this is mentioned in an unaccepted answer to the question linked to by @codingkiwi.com, but I believe the problem is the context in which you're calling FindControl. You are calling Me.FindControl which will search the level 1 children of the page (or user control, or control, or whatever Me is a reference to). You want to be searching the child controls of the actual repeater element, which in this case is the footer. So the search becomes e.Item.FindControl.

It should be noted that there are probably more elegant ways to detect whether or not a repeater control has elements. Perhaps all you need to check for in the OnDataBound event is the footer item, and then look for something like: (my VB may be a bit rusty too)

If (Me.RptEnterHours.Items IsNot Null AndAlso Me.RptEnterHours.Items.Any()) Then
EricTheRed
  • 289
  • 5
  • 14
0

Not sure why its just not enabled in the first place, but this will work since it will fire for the footer after the Item/AlternatingItem types:

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
NoAlias
  • 9,218
  • 2
  • 27
  • 46
0

The reason you get the Object null reference exception is because you are fixated on the cast, which isn't causing the problem. You can generally safely cast the results of FindControl implicitly. What you need to explicitly check for is a null reference AFTER the FindControl results are captured.

Also, you should be looking for ListItemType.Footer so you can reference the footer row.

Finally, FindControl() is not recursive. It only finds controls within the top-level naming container. In most databound controls, each row represents its own naming container, so you must FindControl within the row you want to search. When you use Me, it refers to the page. You should instead use e.Item.FindControl().

Code:

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
pseudocoder
  • 4,314
  • 2
  • 25
  • 40