4

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

然后用户更改这些值并点击页面上的提交按钮,该按钮连接到“submit_click”事件。此事件调用 PhoneInfo 中的 GetPhone() 函数。返回的值包含所有新用户输入的值,除了 phoneId 值(存储在 ViewState 中且未由用户编辑)始终返回为 null。

我相信视图状态负责在回发中跟踪用户输入的数据,所以我无法理解用户值是如何返回的,但不是明确设置的 ViewState[“PhoneId”] 值!如果我在 PhoneInfo 的 page_load 事件中设置 ViewState["PhoneId"] 值,它会在回发后正确检索它,但这不是一个选项,因为我只能在页面准备好提供它时初始化该值。

我确定我只是以某种方式弄乱了页面生命周期,任何建议或问题都会有帮助!我在下面包含了一个非常简化的实际代码版本。

包含页面的代​​码隐藏

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

4 回答 4

1

ViewState 在 Init 和 Load 事件之间进行管理。当您关心维护来自回发的值时,您应该使用从 Page_Init 处理程序而不是 Page_Load 调用的代码或函数。

有关 ASP.NET 页面生命周期的更多信息,请参阅此链接。

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

于 2010-03-31T17:41:50.790 回答
1

像回答者一样,我认为存在这个问题是因为我设置 ViewState 变量太晚而无法在 SaveViewState 期间保存。但是,我为 SaveViewState 事件添加了一个覆盖,果然我在保存 ViewState 之前很久就设置了我的 ViewState 变量。很久以前,事实证明。

显然,在初始化之后,.net 会运行 TrackViewState(),它实际上开始监听您添加的任何 viewState 变量。因为我在 TrackViewState() 运行之前设置了这个 viewState 值,所以一切看起来都很好,但在 SaveViewState 期间实际上并没有添加这些值。我在设置变量之前明确地调用了 TrackViewState() 并且一切都按预期工作。

我的最终解决方案是通过初始化分配一个私有属性来保存 ID 值,然后在 SaveViewState 期间从属性值设置 viewState 变量。通过这种方式,我可以确保 TrackViewState 已由 .net 运行,而无需显式调用它并打乱事情的流程。我在 page_load 上重新加载 viewState 值并使用它来设置属性的值,然后我可以在 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;
}
于 2010-04-01T14:17:37.777 回答
0

要准确地执行您正在做的事情,您必须在Init页面生命周期的一部分中加载控件。

但是,为了更容易做到这一点,为什么不将它添加到<asp:ContentPlaceHolder>? 我认为这将使这变得容易得多。

于 2010-03-31T17:43:32.700 回答
0

根据评论回复,我在这里添加另一个答案,解释页面生命周期的一部分以及它对帖子和视图状态数据的意义。下面是更多的英语(对开发人员),而不是关于页面生命周期开始的事件版本:

  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 不再有机会使用正确的数据填充它。

于 2010-03-31T18:08:22.653 回答