.net ViewState в жизненном цикле страницы - PullRequest
3 голосов
/ 31 марта 2010

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

Затем пользователь изменяет эти значения и нажимает кнопку отправки на странице, которая связана с событием submit_click. Это событие вызывает функцию GetPhone () в PhoneInfo. Возвращаемое значение содержит все введенные пользователем новые значения, за исключением того, что значение phoneId (хранится в ViewState и НЕ редактируется пользователем) всегда возвращается как нулевое.

Я считаю, что viewstate отвечает за отслеживание введенных пользователем данных через обратную передачу, поэтому я не могу понять, как возвращаются пользовательские значения, но не явно установленное значение ViewState ["PhoneId"]! Если я установлю значение ViewState ["PhoneId"] в событии pageInload 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 codebehind

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;
    }
}

Ответы [ 4 ]

1 голос
/ 01 апреля 2010

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

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

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

В этой статье говорится о 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 голосов
/ 31 марта 2010

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

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

0 голосов
/ 31 марта 2010

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

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

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

0 голосов
/ 31 марта 2010

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

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

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

...