在页面生命周期.NET的ViewState生命周期、页面、ViewState、NET

2023-09-05 02:24:18 作者:无意流浪

我有一个包含一个名为PhoneInfo.ascx控件的页面。 PhoneInfo使用LoadControl()和动态创建然后initControl()函数被调用传递初始化对象内PhoneInfo设置一些初始文本框的值。

然后,用户改变这些值,并击中这是有线上升到submit_click事件页面上的提交按钮。此事件调用内PhoneInfo的GetPhone()函数。返回的值具有的所有新用户的进入除了phoneId值(存储在ViewState中和用户不能编辑)总是回来为空值。

我相信,视图状态是负责将用户输入的轨道数据通过回传,所以我无法理解用户值回来了,但没有明确设置的ViewState [PhoneId]值!如果我设置的ViewState [PhoneId在PhoneInfo的Page_Load事件的价值,它的回发后正确检索它,但是这是不是一种选择,因为我只能初始化值,当页面准备提供它。

我敢肯定,我只是搞乱了页面生命周期在某种程度上,任何建议或疑问,将真正帮助!我已经包括了实际的code以下一个非常简化版本。

包含页面的codebehind

 保护无效的Page_Load(对象发件人,EventArgs的)
{
    电话电话= controlToBind的电话;
    PhoneInfo phoneInfo =(PhoneInfo)LoadControl(phoneInfo.ascx); //创建phoneInfo控制
    phoneInfo.InitControl(电话); //使用controlToBind初始化新的控制
    Controls.Add被(phoneInfo);
}
保护无效submit_click(对象发件人,EventArgs的)
{
    电话电话= phoneInfo.GetPhone();
}
 

PhoneInfo.ascx codebehind

 保护无效的Page_Load(对象发件人,EventArgs的)
{
}

公共无效InitControl(手机电话)
{
    如果(手机!= NULL)
    {
        的ViewState [PhoneId] = phone.Id;
        txt_area code.Text = SafeConvert.ToString(phone.Area code);
        txt_number.Text = SafeConvert.ToString(phone.Number);
        ddl_type.SelectedValue = SafeConvert.ToString((INT)phone.Type);
    }
}

公用电话GetPhone()
{
    电话电话=新手机();
    如果((int)的视图状态[PhoneId]≥= 0)
        phone.Id =(INT)的ViewState [PhoneId];
        phone.Area code = SafeConvert.ToInt(txt_area code.Text);
        phone.Number = SafeConvert.ToInt(txt_number.Text);
        phone.Type =(PhoneType)Enum.ToObject(typeof运算(PhoneType),SafeConvert.ToInt(ddl_type.SelectedValue));
        回电话;
    }
}
 

解决方案

我想,像答复者,这个问题存在,因为我设置的ViewState变量来不及SaveViewState过程中进行保存。不过,我增加了一个覆盖为SaveViewState事件,果然我设置ViewState中保存多久,我的ViewState变量。过不久,事实证明。

初​​始化后显然,.NET运行TrackViewState(),它实际上开始监听任何视图状态变量添加。既然我已经设置此视图状态值之前TrackViewState()已经运行,一切都显得很好,但实际上并不SaveViewState过程中被添加的值。我明确叫TrackViewState()前右侧设置变量,一切工作正常。

我最后的解决办法是分配私有财产持有,直至初始化的ID值,然后SaveViewState期间从属性值设置视图状态变量。这样我可以保证TrackViewState已经无需显式调用它扰乱了事物的流量一直由.NET。我重装上的Page_Load视图状态值,并用它来设置属性,我可以那么我GetPhone函数中使用的值。

有关的EnableViewState这文章会谈

 私人INT _id = -1;

保护无效的Page_Load(对象发件人,EventArgs的)
{
    如果(的ViewState [PhoneId]!= NULL)
    _id = SafeConvert.ToInt(的ViewState [PhoneId]);
}

保护覆盖对象SaveViewState()
{
    的ViewState [PhoneId] = _id;
    返回base.SaveViewState();
}

公用电话GetPhone()
{
    电话电话=新手机();
    phone.Id = _id;
    phone.Area code = SafeConvert.ToInt(txt_area code.Text);
    phone.Number = SafeConvert.ToInt(txt_number.Text);
    回电话;
}
 
精 谈谈.net对象生命周期

I have a page containing a control called PhoneInfo.ascx. PhoneInfo is dynamically created using LoadControl() and then the initControl() function is called passing in an initialization object to set some initial textbox values within PhoneInfo.

The user then changes these values and hits a submit button on the page which is wired up to the "submit_click" event. This event invokes the GetPhone() function within PhoneInfo. The returned value has all of the new user entered values except that the phoneId value (stored in ViewState and NOT edited by the user) always comes back as null.

I believe that the viewstate is responsible for keeping track of user entered data across a postback, so I can't understand how the user values are coming back but not the explicitly set ViewState["PhoneId"] value! If I set the ViewState["PhoneId"] value in PhoneInfo's page_load event, it retrieves it correctly after the postback, but this isn't an option because I can only initialize that value when the page is ready to provide it.

I'm sure I am just messing up the page lifecycle somehow, any suggestion or questions would really help! I have included a much simplified version of the actual code below.

Containing page's codebehind

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

解决方案

I thought, like the answerers, that this problem existed because I was setting the ViewState variable too late to be saved during SaveViewState. However, I added an override for the SaveViewState event, and sure enough I was setting my ViewState variable long before the ViewState was saved. Too long before, it turns out.

Apparently after initialization, .net runs TrackViewState() which actually starts listening for any viewState variables you add. Since I had set this viewState value BEFORE TrackViewState() had run, everything appeared fine but the values were not actually being added during SaveViewState. I explicitly called TrackViewState() right before setting the variable and everything worked as expected.

My final solution was to assign a private property to hold the ID value through initialization and then to set the viewState variable during SaveViewState from the property value. This way I can ensure that TrackViewState has been run by .net without having to explicitly call it and mess up the flow of things. I reload the viewState value on page_load and use it to set the value of the property which I can then use in my GetPhone function.

This article talks about 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;
}