Проблемы жизненного цикла веб-элементов управления: страница, сетка и диалоговое окно (содержащее динамический элемент управления, тип которого зависит от выбранной строки в сетке)

У меня есть веб-страница с GridView. GridView содержит список объектов вопросов. У каждого вопроса есть тип вопроса. Когда пользователь щелкает элемент управления «Вопрос», появляется модальное всплывающее окно Ajax, содержащее настраиваемый веб-элемент управления Dialog. Веб-элемент управления Dialog предназначен для инкапсуляции дочернего настраиваемого веб-элемента управления вместе с кнопками ОК и Отмена. В этом сценарии дочерний элемент управления - это настраиваемый элемент управления «Вопрос», представляющий выбранный вопрос. Точный тип элемента управления «Вопрос» неизвестен, пока не будет нажата строка в GridView.

Подводя итог иерархии страниц:

  • Страница
  • GridView, содержащий вопросы (объявленный в разметке .aspx, запускает событие при щелчке строки)
  • Панель связана с модальным расширителем всплывающих окон AJAX (объявленным в разметке .aspx)
  • Элемент управления диалогом (объявлен в разметке .aspx)
  • Элемент управления вопросом (создается динамически в элементе управления Dialog, тип не известен, пока не будет выбран вопрос)
  • Кнопка ОК (создается динамически в элементе управления Dialog)
  • Кнопка отмены (создается динамически в элементе управления Dialog)

Когда пользователь нажимает кнопку ОК в диалоговом окне, я хочу получить доступ к содержимому диалогового окна с содержащей его страницы. (В различных элементах управления Вопросом есть код, который проверяет ответ, и свойство в диалоговом окне, которое предоставляет ответ на содержащую страницу.)

У меня были большие проблемы с тем, чтобы заставить это работать.

Я часами гуглил, и во всех статьях о настраиваемых веб-элементах управления говорится, что вам нужно создавать дочерние элементы управления в переопределении OnInit. Однако в моем сценарии метод Dialog OnInit вызывается до того, как GridView запускает событие щелчка по строке, что означает, что я не могу создать элемент управления Question, потому что я не знаю целевой тип.

Я могу сделать так, чтобы он, по крайней мере, отображал динамический элемент управления вопросом, если переместил код, который его создает, на более позднюю точку жизненного цикла диалога, например. RenderContents. Однако это неверно согласно всем статьям и в любом случае бесполезно, потому что элемент управления все еще недоступен при нажатии кнопки ОК в диалоговом окне (поскольку диалоговое окно скрыто и RenderContents никогда не будет вызван).

Итак, я спрашиваю ребят из ASP.NET, как это должно быть сделано? Я не ищу код; просто стратегия. Как правильно это настроить? Целью является диалоговое окно, которое содержит динамически создаваемый элемент управления, тип которого зависит от выбранной строки в GirdView и к которому может получить доступ содержащаяся страница после обратной передачи.

Будем признательны за любые советы.

ОБНОВИТЬ

Я добавил ведение журнала, и порядок срабатывания событий после щелчка по сетке следующий:

  • Страница ctor
  • Диалог ctor
  • Диалог OnInit
  • Страница OnInit
  • Страница CreateChildControls
  • Диалог CreateChildControls
  • Страница OnLoad
  • Диалог OnLoad
  • Страница OnContactorComplianceQuestionSelected
  • Диалог RenderContents

Я знаю только, какой тип управления должен содержать диалог после Page OnContactorComplianceQuestionSelected.


person J M    schedule 02.11.2009    source источник


Ответы (1)


Не создавайте динамические элементы управления в OnInit - это слишком рано в жизненном цикле и приведет вас в неприятную кроличью нору. Вместо:

  • В обработчике событий Click (в конце жизненного цикла) храните в ViewState или Session идентификатор вопроса или любую другую информацию, необходимую для определения элементов управления для создания. Затем добавьте элементы управления. Поэтому, когда страница возвращается пользователю, элементы управления будут присутствовать.

  • В CreateChildControls проверьте, содержит ли ViewState идентификатор вопроса, и если да, повторно добавьте элементы управления оттуда. Поэтому, когда пользователь повторно отправляет страницу, на этот раз в жизненном цикле, вы можете восстановить дерево элементов управления, как оно должно быть.

Так что-то вроде:

private void AddQuestionControls(int questionID)
{
    //create and add question controls
}

void Handle_Click(object sender, EventArgs e)
{
    //determine question ID
    ViewState["QuestionID"] = questionID;
    AddQuestionControls(questionID);
}

override void CreateChildControls()
{
    if(ViewState["QuestionID"] != null)
    {
        AddQuestionControls(Convert.ToInt32(ViewState["QuestionID"]);
    }
}
person Rex M    schedule 02.11.2009
comment
Спасибо за ответ. Я попробую это сейчас. - person J M; 02.11.2009
comment
@JM это относится только к главной странице, конечно, не к диалогу ... главная страница должна улавливать возврат диалога и обрабатывать его. Это может быть отдельный вопрос, но если вы хотите его опубликовать, я тоже постараюсь вам помочь. - person Rex M; 02.11.2009
comment
Я добавил запись в журнал и, глядя на результаты, кажется, что и OnInit, и CreateChildControls (для страницы и диалогового окна) вызываются до того, как сработает событие щелчка. Я обновил вопрос выводом моего журнала. - person J M; 02.11.2009
comment
@JM да, CreateChildControls обязательно сработает перед событием щелчка и перед PageLoad. Смысл моего ответа - вставить динамические элементы управления в обратную передачу next в CreateChildControls, а не в тот, где запускается событие click. - person Rex M; 02.11.2009
comment
@Rex - Если динамические элементы управления вставляются только в следующую обратную передачу, я не совсем понимаю, как мой диалог будет правильно отображаться при первом щелчке пользователя по сетке? - person J M; 02.11.2009
comment
@JM динамические элементы управления должны быть добавлены из обработчика событий - ничего страшного, если это произойдет на очень позднем этапе жизненного цикла. Их нужно только добавить на раннем этапе следующей обратной передачи, после текущей, из-за которой они были добавлены впервые. - person Rex M; 02.11.2009
comment
И снова привет Рекс за ответ. У меня на это закончилось время, и мне пришлось изменить стратегию. Я думаю, что в текущей реализации есть и другие проблемы, вызывающие побочные эффекты. Я собираюсь принять это как ответ, а затем составить сокращенный тест того, что я пытаюсь сделать. Если я не могу заставить тест работать, я отправлю тестовый код. Между тем, большое спасибо за вашу помощь. - person J M; 03.11.2009