FindControl не находит дочерний элемент управления при обратной передаче

Это меня озадачило, потому что тот же код FindControl находит элемент управления, когда это не обратная передача. Вот такая ситуация.

У меня есть настраиваемый элемент управления (ClassCell.ascx). У него есть LoginView, который показывает ссылку только для людей с определенной ролью.

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

Ссылка называется btnEdit.

В моем настраиваемом элементе управления есть метод SetClass, в котором я использую FindControl, чтобы найти элемент управления btnEdit, а затем установить, на что должен указывать его href.

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

Я динамически добавляю свой настраиваемый элемент управления на этапе PreRender моей страницы Registration.aspx, и сразу после этого я вызываю его метод SetClass.

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

Почему косвенно? На самом деле это немного сложнее, так как есть несколько вложенных настраиваемых элементов управления. Но все действие происходит в PreRender, где я указал. Я создаю настраиваемый элемент управления RoomTable. Внутри этого создаются настраиваемые элементы управления ScheduleRow, и именно в методе ScheduleRow создаются элементы управления CellClass. Я не уверен, что это вложение имеет значение.

Это отлично работает при начальной загрузке страницы, когда это не postBack. Но на главной странице также есть кнопка, с помощью которой вы можете перейти на следующую или предыдущую неделю. Вот тут-то и появляется обратная передача. И когда я просматриваю приведенный выше код в обратной передаче, я вижу, что FindControl ничего не возвращает. Я также вижу, что LoginView1.Controls.Count = 0, поэтому, похоже, это не просто рекурсивный просмотр иерархии элементов управления. Я не понимаю, почему при обратной передаче нет контроля.

И еще более странно то, что «кнопка редактирования» на самом деле отображается, но гиперссылка не активна, поскольку мой код не смог ее установить, поскольку элемент управления не может быть найден. Так что это похоже на временную привязку, когда я пытаюсь с ней работать, но нет контроля, но есть позже. Не подходящее ли время для PreRender делать это?

Заранее спасибо за помощь. Надеюсь, мне просто не хватает чего-то простого. Сандра


person Sandra    schedule 27.03.2014    source источник
comment
Когда вы звоните в FindControl? Если он находится до PreRender (где вы добавляете кнопку), он не найдет его, потому что он еще не создан.   -  person KVM    schedule 27.03.2014
comment
Вам нужно повторно привязать его, чтобы он был повторно отрисован.   -  person MMK    schedule 27.03.2014
comment
@Sandra Не могли бы вы изменить его серверный элемент управления ASP.Net HyperLink и протестировать его снова?   -  person Win    schedule 27.03.2014
comment
@Michael - надеюсь, моя редакция проясняет. Это все во время PreRender.   -  person Sandra    schedule 31.03.2014
comment
@MMK - Это предложение звучит многообещающе. Но не могли бы вы пояснить, что вы подразумеваете под повторным связыванием? Это не связанный контроль.   -  person Sandra    schedule 31.03.2014
comment
@Win - пробовал, но почему-то не хотелось работать даже при начальной загрузке страницы. Ссылки были там, и я мог видеть, как NavigateURL настраивается на мои желаемые URL-адреса, но при отображении все ссылки указывали на страницу регистрации, а не на заданные URL-адреса.   -  person Sandra    schedule 31.03.2014


Ответы (2)


Обработчики событий PostBack вызываются раньше, чем событие PreRender. Вы должны динамически добавлять элементы управления в событие Init.

person Ivan Doroshenko    schedule 27.03.2014
comment
Вместо этого вам может понадобиться событие Load, если вам нужно получить доступ к Viewstate - person KVM; 27.03.2014
comment
@Ivan - Мне нужно обработать PostBack, прежде чем я начну отображать расписание занятий, потому что это обработчик кнопок Предыдущая / Следующая неделя устанавливает даты для отображаемых классов. Я попытался перенести свой код PreRender в Init, но когда я меняю недели, он больше не работает. - person Sandra; 31.03.2014
comment
@Michael - я не использую ViewState, только несколько переменных в Session. Я пробовал Загрузить раньше, но, похоже, это происходит до того, как будет обработано нажатие кнопки Предыдущая неделя / Следующая неделя, поэтому неделя фактически не меняется, и отображается расписание той же недели. - person Sandra; 31.03.2014

Боюсь, что я обошел проблему, отказавшись от использования LoginView. Вместо этого я просто добавил код, чтобы решить, делать ли ссылку видимой или нет, в зависимости от роли текущего пользователя.

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

Большое спасибо за все ответы. Если кто-то считает, что вопрос следует удалить, потому что на него нет точного ответа, во что бы то ни стало дайте мне знать, и я могу его удалить. Очевидно, есть некоторый нюанс в использовании элемента управления LoginView во (вложенном) пользовательском элементе управления и его времени / поведении при загрузке первой страницы по сравнению с обратной передачей.

Спасибо! Сандра

person Sandra    schedule 31.03.2014