I have a fairly straightforward repeater fed by a DataTable. There are elements in the ItemTemplate set to visible=false. In the ItemDataBound event I toggle visibility and such based on what's in the DataTable. All works well enough except that the final row of the repeater gets its base data but not any of the changes from the ItemDataBound event. I can step through execution and watch them get changed in the codebehind, but those changes are not reflected in the ASPX. This only happens for the final row (or only row if only one record is returned). If I return four rows, I get three rows of correct buttons and such, and a fourth row with only unmodified base data.
I have created a new repeater on the page, and then stripped it down to the very basics. I have played with the ClientIdMode and the .NET framework version. I have triple-checked the tag formatting, removed anything non-essential and rebooted every computer in the building twice. I have turned ViewState on and off, I have removed IsPostBack checks, and I have renamed the repeater. I am not using nested repeaters (elsewhere in the project, but not on this page), I am not using validation, and I have removed all my CommandArg stuff.
My ASPX:
<asp:repeater ID="rptrTEST" runat="server" Visible="true">
<ItemTemplate>
<span ID="TESTspanParticipantCSI" visible="true" runat="server">
CSI: <%#Eval("MoodleID")%>
</span>
<br />
<img src="../images/projectname/btn-add-subscriber-20.png"
class="TESTbtnSubscriber TESTbtnParticipantSubscribe"
ID="TESTbtnParticipantSubscribe"
alt="Subscribe participant cell phone"
visible="false"
runat="server" />
<asp:ImageButton
ID="TESTbtnParticipantPause"
CssClass="TESTbtnSubscriber TESTbtnPause TESTbtnParticipantPause"
Visible="false"
ImageURL="~/images/projectname/btn-pause-subscriber-20.png"
runat="server" />
<asp:ImageButton
ID="TESTbtnParticipantPlay"
CssClass="TESTbtnSubscriber TESTbtnPlay TESTbtnParticipantPlay"
Visible="false"
ImageURL="~/images/projectname/btn-play-subscriber-20.png"
runat="server" />
<asp:ImageButton
ID="TESTbtnParticipantUnsubscribe"
CssClass="TESTbtnParticipantUnsubscribe"
Visible="false"
ImageURL="../images/projectname/btn-delete-subscriber-20.png"
runat="server" />
<br />
</ItemTemplate>
</asp:repeater>
My VB:
Protected Sub rptrTEST_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptrTEST.ItemDataBound
Dim objCSIs As New Reg_DB.clsSubscribers
Dim dtCSIs As Data.DataTable = objCSIs.GetAllCSIs()
Dim y As Integer = 0
For Each rptItem As RepeaterItem In rptrTEST.Items
Dim spanParticipantCSI As New HtmlGenericControl
Dim btnParticipantSubscribe As HtmlImage = DirectCast(rptrTEST.Items(y).FindControl("TESTbtnParticipantSubscribe"), HtmlImage)
Dim btnParticipantUnsubscribe As ImageButton = DirectCast(rptrTEST.Items(y).FindControl("TESTbtnParticipantUnsubscribe"), ImageButton)
Dim btnParticipantPause As ImageButton = DirectCast(rptrTEST.Items(y).FindControl("TESTbtnParticipantPause"), ImageButton)
Dim btnParticipantPlay As ImageButton = DirectCast(rptrTEST.Items(y).FindControl("TESTbtnParticipantPlay"), ImageButton)
If dtSubscribersCooked.Rows(y)("ParticipantSubStatus") = "NONE" then
spanParticipantCSI.InnerHtml = "subscribed"
btnParticipantUnsubscribe.Visible = true
btnParticipantPause.Visible = true
btnParticipantSubscribe.Visible = false
spanParticipantCSI.InnerHtml = "subscribed"
btnParticipantPlay.Visible = false
else
spanParticipantCSI.InnerHtml = "whatever"
btnParticipantUnsubscribe.Visible = true
btnParticipantPause.Visible = true
btnParticipantSubscribe.Visible = false
spanParticipantCSI.InnerHtml = "sure"
btnParticipantPlay.Visible = false
end if
y=y+1
next
End Sub
So do I need an old priest and a young priest, or will this require shamans instead?
This is because the count of the items in the repeater isn't what you are expecting. When you loop through each item in the repeater's collection, it only knows of the items that have already been bound. Since your last item hasn't been bound yet (it is currently being bound), it doesn't see that item.
What you need to do is get rid of that For Each
loop entirely. Then just edit the RepeaterItem
that is currently being bound. Notice how I find each control for the current item: e.Item.FindControl()
Protected Sub rptrTEST_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptrTEST.ItemDataBound
Dim objCSIs As New Reg_DB.clsSubscribers
Dim dtCSIs As Data.DataTable = objCSIs.GetAllCSIs()
Dim spanParticipantCSI As New HtmlGenericControl
Dim btnParticipantSubscribe As HtmlImage = DirectCast(e.Item.FindControl("TESTbtnParticipantSubscribe"), HtmlImage)
Dim btnParticipantUnsubscribe As ImageButton = DirectCast(e.Item.FindControl("TESTbtnParticipantUnsubscribe"), ImageButton)
Dim btnParticipantPause As ImageButton = DirectCast(e.Item.FindControl("TESTbtnParticipantPause"), ImageButton)
Dim btnParticipantPlay As ImageButton = DirectCast(e.Item.FindControl("TESTbtnParticipantPlay"), ImageButton)
If dtSubscribersCooked.Rows(y)("ParticipantSubStatus") = "NONE" then
spanParticipantCSI.InnerHtml = "subscribed"
btnParticipantUnsubscribe.Visible = true
btnParticipantPause.Visible = true
btnParticipantSubscribe.Visible = false
spanParticipantCSI.InnerHtml = "subscribed"
btnParticipantPlay.Visible = false
else
spanParticipantCSI.InnerHtml = "whatever"
btnParticipantUnsubscribe.Visible = true
btnParticipantPause.Visible = true
btnParticipantSubscribe.Visible = false
spanParticipantCSI.InnerHtml = "sure"
btnParticipantPlay.Visible = false
end if
End Sub
I'm not sure what dtSubscribersCooked
is or where it is declared. If that is a global variable or something, then an option for you may be to bind ParticipantSubStatus
to a HiddenField on your repeater to get it's value on each ItemDataBound.