为什么DropDownList.SelectedValue依赖于viewstate?

时间:2013-08-06 10:30:59

标签: asp.net forms viewstate

如果我在我的页面上设置:EnableViewState="true" ViewStateMode="Disabled" - 那么 - 该页面禁用Viewstate(除非覆盖......

然后,尝试读取(假设控件已在最后一次转储中填充到屏幕并选择了值):

MyDDL.SelectedValue将产生""

这是因为禁用了viewstate:

但我的问题是更高层次:

  • 如果它只是一个表单值(我仍然可以从Request.Form[MyDDL.UniqueID]获得) - 我们正在谈论一个不需要保存其值的输入。

  • 为什么名为DropDownList的{​​{1}}属性是否依赖于ViewState?

P.S。 TextBox onchangeevent 确实依赖于viewstate,虽然控件是一个输入(不需要viewstate) - 它保存了文本的值,然后在回发时比较它。但是它只依赖于viewstate设置onchange事件(和autopostback)

4 个答案:

答案 0 :(得分:7)

SelectedValue依赖于ViewState,因为在PostBack上,它会从ListItems重建其ViewState,然后在DropDownList上设置所选值{ {1}}对象。

未将Request值直接作为Request。这反过来是因为,ASP.Net可以检查发布的SelectedValue是否未被客户端篡改。它是通过首先从DropDownList反序列化原始项目来实现的。然后,它会在项目中找到ViewState值,并将其Request属性设置为Selected。只有现在,true属性可用。 (或SelectedValue就此而言)。它应该能够立即触发SelectedIndex事件。

这也是您不需要在SelectedIndexChanged中再次绑定DropDownList的原因。列表项目是从PageLoad自动检索的。

如果ViewState被禁用,则ViewState中将没有原始列表项,并且该列表项将为空。因此,它将无法将任何项目标记为已选中。因此ViewState将为0或SelectedValue将为空。我认为SelectedItem事件也不会发生。对于在这种情况下工作的事情,需要进行数据绑定,最好是SelectedIndexChanged

然而,有一些解决方法。

完整参考:http://msdn.microsoft.com/en-us/library/ms972976.aspx

编辑 :(在Op的评论之后)

按照网页生命周期查看init依赖SelectedValue的位置:

Stage 1 Init :构建控件层次结构。如果此处绑定了DropDownList或者以声明方式添加了ListItem,则会在此处填充List。

第2阶段加载ViewState :在PostBack上,ViewState在此处得到验证并加载到DropDownList中。此处有 ViewState

第3阶段加载PostBack数据:此处获取SelectedValue值(来自表单请求),然后应用于控件。在Request的情况下,现在设置来自收到的DropDownList对象值的SelectedValue,内部实现是这样的:

Request

这里重要的是,如果ViewState不存在且DropDownList不是数据绑定的,那么ListItem集合将为空,因此string selectedValue = HttpContext.Current.Request.Form[DropDownList_Id]; Items.FindByValue(selectedValue).Selected = true; 属性为0.这与内部实现无关属性。

如果ViewState不存在(禁用)且DropDownList是数据绑定的,则ListItem集合将存在,相应的项将被标记为选中,因此SelectedValue属性将返回正确的值。

如果项目集合是新的(通过重新绑定不同的数据集或ViewState无效),则在项目集合中找不到SelectedValue表单值,并再次Request将无效。

第4阶段页面加载:此时已加载ViewState(或数据绑定)和PostBack数据。

第5阶段提升PostBack事件:在此阶段,如果在阶段3中更改了索引,则会触发DropDownList的SelectedValue事件。

因此,OnSelectedIndexChanged依赖于阶段3的ViewState。当然,如果控件是适当的数据绑定,那么它将不依赖于ViewState作为推论。

SelectedValue依赖于ViewState来确保在设置之前填充了项目集合。数据绑定/重新绑定只是确保填充项目集合的另一种方法。

希望澄清。

答案 1 :(得分:6)

摘要:如果您希望控件在没有ViewState的情况下工作,则需要在每次回发时填充/绑定Items集合。我建议在Page_Init事件中使用它(即OnInit方法)。

首先,我总是推荐这篇很棒的文章:TRULY Understanding ViewState.

SelectedValue不需要ViewState。查看DropDownList继承自的ListControl的代码,我们看到代码:

public virtual string SelectedValue
{
  get
  {
    int selectedIndex = this.SelectedIndex;
    if (selectedIndex >= 0)
      return this.Items[selectedIndex].Value;
    else
      return string.Empty;
  }

从这段代码中删除的重要一点是必须填充Items列表以获取SelectedValue。

如果您使用ViewState,则Item集合 将持久保存到/从ViewState加载,这允许SelectedValue属性在不重新绑定控件的情况下工作。

答案 2 :(得分:0)

      protected void Page_Load(object sender, EventArgs e)
            {
                (!Page.IsPostBack)
                {
                    string qry = "SELECT TOP(5)xxx, xxxx FROM dbo.xxxxxx ";
                    DataSet ds = new DataSet();
                    ds = SqlHelper.ExecInDS(qry);
                    drpDwn.DataSource = ds.Tables[0];
                    drpDwn.DataValueField = Convert.ToString(ds.Tables[0].Columns["xxx"]);
                    drpDwn.DataTextField = Convert.ToString(ds.Tables[0].Columns["xxx"]);                   
                    drpDwn.DataBind();
                }
               //Here You will get selected value from dropdown
               string sss= Request.Form["drpDwn"];
    }

答案 3 :(得分:0)

如果你希望DropDownList在没有ViewState的情况下工作,你可以只在page_load中绑定一次控件,如下所示:

        ps.setString(1, camper.getFirstName());
        ps.setString(2, camper.getLastName());
        ps.setString(3, camper.getDob());
        ps.setString(4, camper.getParentName());
        ps.setString(5, camper.getEmail());
        ps.setDouble(6, camper.getTotalPaid());
        ps.setLong(7, camper.getId());
  • 在这种情况下(ViewState被禁用),Asp.net FrameWork会从每个PostBack的后端检索项目。

  • 在这种情况下(启用ViewState),Asp.net FrameWork从ViewState中检索项目而不用每个PostBack命中后端

通常,Asp.net FrameWork在PreRender事件中触发数据绑定事件:阅读ASP.NET Page Life Cycle Overview

您可以通过启用跟踪来确认该行为。

SelectedValue不直接依赖source code of ListControl的ViewState ,但依赖于上述项目。