0

This has me baffled because the same FindControl code finds the control when it's not a postback. Here's the situation.

I have a custom control (ClassCell.ascx). It has a LoginView that shows a link only for people in a particular role.

...
<asp:LoginView ID="LoginView1" runat="server">
    <RoleGroups>
        <asp:RoleGroup Roles="Instructor">
            <ContentTemplate>
                <a id="btnEdit" class="cssButtonPink" runat="server" href="">Edit</a>
            </ContentTemplate>
        </asp:RoleGroup>
    </RoleGroups>
</asp:LoginView>
...

So the link is called 'btnEdit'.

My custom control has a method called SetClass, where I use FindControl to find the 'btnEdit' control, and then set what its href should point to.

Public Sub SetClass
    ...
    Dim editButton As HtmlAnchor = Me.LoginView1.FindControl("btnEdit")
    If editButton IsNot Nothing Then
        editButton.HRef = "~/Instructors/ManageClasses.aspx?c=" + ClassID.ToString
    End If
    ...
End Sub

I am dynamically adding my custom control during the PreRender stage of my Signup.aspx page, and immediately after, I'm calling its SetClass method.

Private Sub ClassSignup_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
    ...
    If IsPostBack Then
        ...
    Else
        ...
    End If
    ...
    ' this is where my misbehaving control is (indirectly) created '
    Dim cc As New ClassCell
    cc = LoadControl("~\Members\ClassCell.ascx")
    cc.SetClass(objClass)
    ...
End Sub

Why Indirectly? It's actually a little more complicated, as there are several nested custom controls. But all of the action happens in PreRender where I indicated. I create a RoomTable custom control. Within that, are created ScheduleRow custom controls, and it is within a method of ScheduleRow that the CellClass controls are created. I'm not sure if this nesting matters.

This works perfectly in the initial page load when it's not a postBack. But there is also a button on the main page where you can advance to the following week or previous week. This is where the postback comes in. And as I step through the above code on a postback, I see that FindControl returns Nothing. I also see that LoginView1.Controls.Count = 0, so it doesn't seem to be a matter of just recursing through the hierarchy of controls. I don't understand why the control isn't there on postback.

And even more strange is that the 'edit button' actually renders, but the hyperlink is not active, since my code failed to set it, since the control could not be found. So it's almost like it's a timing thing, with the control not there when I'm trying to work with it, but there later on. Is PreRender the wrong time to try to be doing this?

Thanks in advance for the help. I hope I'm just missing something simple. Sandra

Sandra
  • 608
  • 2
  • 11
  • 23
  • When do you call FindControl ? If it's before PreRender (where you add the button), then it won't find it because it's not instanciated yet. – KVM Mar 27 '14 at 13:40
  • You need to rebind it so that it's re-rendered. – MMK Mar 27 '14 at 13:42
  • @Sandra Could you change it **ASP.Net HyperLink** server control and test it again? – Win Mar 27 '14 at 14:00
  • @Michael - hopefully my edit clarifies. It's all during PreRender. – Sandra Mar 31 '14 at 13:45
  • @MMK - That suggestion sounds very promising. But could you clarify what you mean by rebind? It is not a bound control. – Sandra Mar 31 '14 at 13:45
  • @Win - I tried, but for some reason, this didn't want to work even on initial page load. The Links were there, and I could see the NavigateURL getting set to my desired URLs, but when rendered, all links pointed to the signup page, rather than the URLs that had been set. – Sandra Mar 31 '14 at 15:14

2 Answers2

0

PostBack event handlers are called earlier than PreRender event. You should dynamically add controls on Init event.

Ivan Doroshenko
  • 944
  • 7
  • 13
  • You may want Load event instead if you need to access the Viewstate – KVM Mar 27 '14 at 13:42
  • @Ivan - I need the PostBack to be processed before I begin displaying the class schedule, because it is the handler of the Previous Week / Following Week buttons that sets that dates of the classes to be displayed. I tried moving my PreRender code to Init, but when I change weeks, it doesn't work right anymore. – Sandra Mar 31 '14 at 14:06
  • @Michael - I don't use any ViewState, only a couple of variables in the Session. I tried Load before, but it seems to happen before the Previous Week / Next Week button press is handled, so the week doesn't actually change, and the same week's schedule is rendered. – Sandra Mar 31 '14 at 14:13
0

I'm afraid I side-stepped the issue by eliminating the use of LoginView. Instead, I just added code to decide whether to make the link visible or not depending on the current user's role.

    If Page.User.IsInRole("Instructor") Then
        btnEdit.HRef = "~/Instructors/ManageClasses.aspx?c=" + ClassID.ToString
        btnEdit.Visible = True
    Else
        btnEdit.Visible = False
    End If

Thanks very much for all the answers. If anyone feels the question should be deleted because it's not truly answered, by all means let me know, and I can delete it. There's obviously some nuance to using the LoginView control, in a (nested) user control, and its timing/behaviour on first page load vs. postback.

Thanks! Sandra

Sandra
  • 608
  • 2
  • 11
  • 23