2010-03-31 2 views
3

У меня есть страница, содержащая элемент управления под названием PhoneInfo.ascx. PhoneInfo динамически создается с помощью LoadControl(), а затем функция initControl() называется передачей в объекте инициализации для установки некоторых исходных значений текстового поля в PhoneInfo..net ViewState в жизненном цикле страницы

Пользователь затем изменяет эти значения и обращается к кнопке отправки на странице, которая подключена к событию «отправить_click». Это событие вызывает функцию GetPhone() в PhoneInfo. Возвращаемое значение имеет все новые введенные пользователем значения, за исключением того, что значение phoneId (сохраненное в ViewState и NOT, отредактированное пользователем) всегда возвращается как null.

Я считаю, что viewstate несет ответственность за отслеживание введенных пользователем данных через обратную передачу, поэтому я не могу понять, как возвращаются значения пользователя, а не явно установленное значение ViewState ["PhoneId"]! Если я установил значение ViewState ["PhoneId"] в событие page_load PhoneInfo, он вернет его правильно после обратной передачи, но это не вариант, потому что я могу инициализировать это значение только тогда, когда страница готова к его предоставлению.

Я уверен, что я как-то испортил жизненный цикл страницы, любое предложение или вопросы действительно помогли бы! Я включил значительно упрощенную версию фактического кода ниже.

Содержит отделенного кода страницы

protected void Page_Load(object sender, EventArgs e) 
{ 
    Phone phone = controlToBind as Phone; 
    PhoneInfo phoneInfo = (PhoneInfo)LoadControl("phoneInfo.ascx"); //Create phoneInfo control 
    phoneInfo.InitControl(phone); //use controlToBind to initialize the new control 
    Controls.Add(phoneInfo); 
} 
protected void submit_click(object sender, EventArgs e) 
{ 
    Phone phone = phoneInfo.GetPhone(); 
} 

PhoneInfo.ascx отделенного кода

protected void Page_Load(object sender, EventArgs e) 
{ 
} 

public void InitControl(Phone phone) 
{ 
    if (phone != null) 
    { 
     ViewState["PhoneId"] = phone.Id; 
     txt_areaCode.Text = SafeConvert.ToString(phone.AreaCode); 
     txt_number.Text = SafeConvert.ToString(phone.Number); 
     ddl_type.SelectedValue = SafeConvert.ToString((int)phone.Type); 
    } 
} 

public Phone GetPhone() 
{ 
    Phone phone = new Phone(); 
    if ((int)ViewState["PhoneId"] >= 0) 
     phone.Id = (int)ViewState["PhoneId"]; 
     phone.AreaCode = SafeConvert.ToInt(txt_areaCode.Text); 
     phone.Number = SafeConvert.ToInt(txt_number.Text); 
     phone.Type = (PhoneType)Enum.ToObject(typeof(PhoneType),  SafeConvert.ToInt(ddl_type.SelectedValue)); 
     return phone; 
    } 
} 

ответ

1

Я думал, как и автоответчики, что эта проблема существует из-за того, что я слишком долго настраивал переменную ViewState для сохранения во время SaveViewState. Тем не менее, я добавил переопределение для события SaveViewState, и, конечно же, я устанавливал переменную ViewState задолго до сохранения ViewState. Оказывается, слишком давно.

По-видимому, после инициализации .net запускает TrackViewState(), который фактически начинает прослушивать любые добавляемые переменные viewState. Поскольку я установил это значение viewState перед запуском TrackViewState(), все оказалось прекрасным, но значения фактически не добавлялись во время SaveViewState. Я прямо называл TrackViewState() прямо перед настройкой переменной, и все работало, как ожидалось.

Моим окончательным решением было назначить частное свойство для хранения значения идентификатора через инициализацию, а затем установить переменную viewState во время SaveViewState из значения свойства. Таким образом, я могу гарантировать, что TrackViewState был запущен .net без необходимости явно называть его и испортить поток вещей. Я перезагружаю значение viewState на page_load и использую его для установки значения свойства, которое затем я могу использовать в своей функции GetPhone.

Этот article говорит о enableViewState.

private int _id = -1; 

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (ViewState["PhoneId"] != null) 
    _id = SafeConvert.ToInt(ViewState["PhoneId"]); 
} 

protected override object SaveViewState() 
{ 
    ViewState["PhoneId"] = _id; 
    return base.SaveViewState(); 
} 

public Phone GetPhone() 
{ 
    Phone phone = new Phone(); 
    phone.Id = _id; 
    phone.AreaCode = SafeConvert.ToInt(txt_areaCode.Text); 
    phone.Number = SafeConvert.ToInt(txt_number.Text); 
    return phone; 
} 
0

ViewState управляется между Init и Load событий. Вы должны использовать код или функции, вызываемые из обработчика Page_Init, а не Page_Load, когда вы обеспокоены сохранением значений из postbacks.

См. Эту ссылку для получения дополнительной информации о жизненном цикле страницы ASP.NET.

http://msdn.microsoft.com/en-us/library/ms178472.aspx

+0

Я понимаю эту часть жизненного цикла и соглашаюсь с тем, что лучшее место для этого находится на странице_иниции. Но почему введенные пользователем значения переходят к моей функции GetPhone, если они были сохранены через postback через viewstate? Должны ли те, кто вернулся, тоже недействительны? – caltrop

0

Для того, чтобы делать то, что вы делаете, вы должны иметь контроль над загруженным в Init части жизненном цикле страницы.

Однако, чтобы сделать это проще, почему бы вам не добавить его в <asp:ContentPlaceHolder>? Думаю, это будет намного проще.

+0

Спасибо за предложение заполнителя, но из-за сложности кода, который я забыл, местозаполнитель здесь не идеален. =) Я понимаю, что жизненный цикл достаточно для того, чтобы знать, что установка этого в Init приведет к сохранению и правильной загрузке ViewState ... Я думаю, я в замешательстве, почему введенный пользователем текст работает, учитывая, что он проходит через viewstate. – caltrop

0

Основываясь на ответах на комментарии, я добавляю здесь еще один ответ, который объясняет часть жизненного цикла страницы и то, что она означает для данных post и viewstate. Ниже приводится более-английски (на разработчика) и меньше о событиях версии в начале жизненного цикла страницы:

  1. Пользователь запрашивает страницу (запрос 1)
  2. ASP.NET создает страницу с умолчанию значения в полях (запрос 1)
  3. на вашем Page_Load, вы добавляете этот специальный контроль с вашими значениями по умолчанию (запрос 1)
  4. вы отправляете эту страницу пользователя (запрос 1)
  5. в сообщения пользовательских данных на страница (запрос 2)
  6. ASP.NET строит t он из вашего ASPX-файла (запрос 2)
  7. ASP.NET добавляет данные ViewState на страницу (в это время их нет) (запрос 2)
  8. ASP.NET добавляет данные на страницу на страницу (запрос 2)
  9. ASP.NET работает до этапа загрузки Жизненный цикл страницы и добавляет ваш специальный контроль с вашими значениями по умолчанию (запрос 2)
  10. Вы находитесь в проблемном состоянии, которое видите.

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

+0

Для того, что стоит, событие «Init» находится между шагами 6 и 7 этого резюме. Более конкретно, этап 6 является событием PreInit. – Jaxidian

+0

Это имеет большой смысл. Я хочу, чтобы мой фактический код позволял мне просто переместить код создания в Page_init, но это не так. Мне придется кое-что выяснить. Спасибо за помощь! – caltrop