9

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

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

MyDDL.SelectedValue将产生""

那是因为禁用了 viewstate :

但我的问题是更高层次的:

  • 如果这完全是关于表单值(我仍然可以从中获取Request.Form[MyDDL.UniqueID]) - 我们正在谈论一个不需要任何东西来保存其值的输入。

  • 为什么DropDownList名为 ( )的属性SelectedValue是依赖于 ViewState 的?

ps TextBox onchangeevent确实依赖于视图状态,尽管控件是输入(不需要视图状态) - 它保存文本的值,然后在回发时进行比较。但它仅在设置 onchange 事件(和自动回发)时依赖于视图状态)

4

4 回答 4

7

SelectedValue依赖,因为它ViewState在 PostBack 上重建它ListItemsViewState然后DropDownListRequest对象上设置选定的值。

它不直接将Request值作为SelectedValue。这反过来又是因为,ASP.Net 可以DropDownList在客户端检查发布的内容是否未被篡改。它首先从ViewState. 然后它在项目中找到Request值并将其Selected属性设置为true。只是现在,该SelectedValue物业是可用的。(或SelectedIndex就此而言)。它现在应该能够触发一个SelectedIndexChanged事件。

这也是不需要DropDownList再次绑定 in的原因PageLoad。列表项会自动从ViewState.

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

但是,有一些解决方法。

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

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

按照页面生命周期查看SelectedValue依赖于何处ViewState

阶段 1 初始化:构建控制层次结构。如果 DropDownList 在此处绑定或已以声明方式添加 ListItems,则在此处填充 List。

第 2 阶段加载 ViewState:在 PostBack 上,此处验证 ViewState 并将其加载到 DropDownList 中。这里没有 SelectedValue

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

string selectedValue = HttpContext.Current.Request.Form[DropDownList_Id];
Items.FindByValue(selectedValue).Selected = true;

这里重要的是,如果 ViewState 不存在且 DropDownList 未绑定数据,则 ListItem 集合将为空,因此SelectedValue属性为 0。这与属性的内部实现无关。

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

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

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

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

因此,SelectedValue在第 3 阶段依赖 ViewState。当然,如果控件是适当的数据绑定,那么它就不会依赖 ViewState 作为推论。

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

希望澄清。

于 2013-08-06T12:56:07.730 回答
6

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

首先,我总是推荐这篇很棒的文章:真正理解 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,Items 集合持久保存到 ViewState/从 ViewState 加载,这允许 SelectedValue 属性在不重新绑定控件的情况下工作。

于 2013-08-06T13:35:11.090 回答
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"];
    }
于 2013-08-06T13:08:36.857 回答
0

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

     protected void Page_Load(object sender, EventArgs e)
            {        
     //whatever you use declarative binding (in aspx page), or define data source  here
                if (!IsPostBack)
                {
                  ddl.DataBind(); //fire databinding events and fill items, and selectedvalue has a value.
                }

                //you can get the selectedvalue
                var sv=ddl.SelectedValue ; //
            }           
  • 在这种情况下(ViewState 被禁用),Asp.net FrameWork 使用每个 PostBack 从后端检索项目。

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

通常,Asp.net FrameWork 在 PreRender 事件中触发数据绑定事件:阅读ASP.NET 页面生命周期概述

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

SelectedValue 不直接依赖于ListControl 源代码中的ViewState ,而是依赖于上述项目。

于 2017-11-06T21:35:14.617 回答