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

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

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

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

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

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

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

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

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

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

UPDATE

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

  • Страница ctor
  • Диалог ctor
  • Диалог OnInit
  • Page OnInit
  • Страница CreateChildControls
  • Диалог CreateChildControls
  • Page OnLoad
  • Dialog OnLoad
  • Страница OnContactorComplianceВопросВыбрано
  • Диалог RenderContents

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

1 Ответ

2 голосов
/ 02 ноября 2009

Не создавайте динамические элементы управления в 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"]);
    }
}
...