如果我在我的页面上设置:EnableViewState="true" ViewStateMode="Disabled"
- 那么 - 该页面禁用Viewstate(除非覆盖...... )
然后,尝试读取(假设控件已在最后一次转储中填充到屏幕并选择了值):
MyDDL.SelectedValue
将产生""
这是因为禁用了viewstate:
但我的问题是更高层次:
如果它只是一个表单值(我仍然可以从Request.Form[MyDDL.UniqueID]
获得) - 我们正在谈论一个不需要保存其值的输入。
为什么名为DropDownList
的{{1}}属性是否依赖于ViewState?
P.S。 TextBox onchangeevent 确实依赖于viewstate,虽然控件是一个输入(不需要viewstate) - 它保存了文本的值,然后在回发时比较它。但是它只依赖于viewstate设置onchange事件(和autopostback)
答案 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 ,但依赖于上述项目。