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

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

Чтобы подвести итог иерархии страниц:

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

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

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

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

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

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

Любые советы будут с благодарностью.

ОБНОВИТЬ

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

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

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

1 ответ

Решение

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

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

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

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

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"]);
    }
}
Другие вопросы по тегам