我认为我很了解ViewState,但以下是给我一些麻烦:
来自 http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx
即使禁用ViewState,回退控件(如下拉列表和文本框)也会恢复其发布状态(下拉列表的选定项目已发布),因为即使禁用了ViewState,控件仍然可以发布其值
假设 DropDownList 将 EnableViewState 设置为false,那么(根据上面的引用)当用户通过选择 DropDownList ,以下代码应导致 Label1.Text 显示所选项的值(因此 DropDownList.SelectedValue 应返回用户选择的值,即使viewstate已禁用),但我得到一个空字符串:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string[] number = {"first","second","third"};
DropDownList1.DataSource = number;
this.DataBind();
}
if (IsPostBack)
{
Label1.Text = DropDownList1.SelectedValue; // displays empty string
// Label1.Text = DropDownList1.SelectedItem.Text; // causes an exception
// Label1.Text = DropDownList1.SelectedIndex.ToString(); // displays empty string
}
}
该文章的作者似乎是这方面的专家,所以我假设我做错了什么!?!
感谢名单
答案 0 :(得分:17)
没有选定的值,因为:
1)下拉列表中没有项目,因为您只是第一次将数据绑定到它。通常这是一种很好的做法,但是当您关闭ViewState时,您必须每次都为控件显式重新创建数据。
2)您正在页面生命周期中将请求字典值应用于控件的点之后(即,在将ViewState恢复到控件期间)绑定数据。发布的值存在于Request字典中,但是从那里开始在下拉列表中没有任何项目,它无法真正做到这一点。即使ViewState已关闭,您的作者也是正确的 - 将在生命周期中通常应用ViewState的点处应用已发布的值。
如果您要在Init()中重新创建列表的数据,那么将填充下拉列表以显示要应用的已发布值,它将被应用,并且所选值将在时间可用你得Load()。希望这很清楚。一些工作代码如下:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
Label1.Text = DropDownList1.SelectedValue;
}
}
protected void Page_Init(object sender, EventArgs e)
{
string[] number = { "first", "second", "third" };
DropDownList1.DataSource = number;
DropDownList1.DataBind();
}
}
答案 1 :(得分:1)
这是一个更智能的DropDownList实现。不是巨魔或任何东西,但我不敢相信有些限制(阅读:愚蠢)一些ASP.Net控件....
Public Class DropDownList
Inherits System.Web.UI.WebControls.DropDownList
Private _SelectedIndex As Integer? = -1
Private _SelectedValue As String = Nothing
Private _StateFromClient As Boolean = False
Private _StateFromLocal As Boolean = False
Protected Overrides Sub OnInit(ByVal e As EventArgs)
MyBase.OnInit(e)
Page.RegisterRequiresControlState(Me)
End Sub
Public Overrides Property SelectedIndex() As Integer
Get
If Not _StateFromLocal Then
Me.LoadStateFromClient()
If _StateFromClient Then
Return _SelectedIndex
End If
End If
Return MyBase.SelectedIndex
End Get
Set(ByVal value As Integer)
_StateFromLocal = True
MyBase.SelectedIndex = value
End Set
End Property
Public Overrides Property SelectedValue() As String
Get
If Not _StateFromLocal Then
LoadStateFromClient()
If _StateFromClient Then
Return _SelectedValue
End If
End If
Return MyBase.SelectedValue
End Get
Set(ByVal value As String)
_StateFromLocal = True
MyBase.SelectedValue = value
End Set
End Property
Private Sub LoadStateFromClient()
If _StateFromClient Then Return
If _StateFromLocal Then Return
If Me.IsViewStateEnabled Then Return
If Not Me.Page.IsPostBack Then Return
If Not _SelectedIndex.HasValue Then
Throw New Exception("ControlState has not yet been loaded and so state does not exist.")
End If
_SelectedValue = Me.Page.Request.Form(Me.UniqueID)
_StateFromClient = True
End Sub
Protected Overrides Sub PerformSelect()
' Called when DataBound() is called, which can affect the Selected* property values
_StateFromLocal = True
MyBase.PerformSelect()
End Sub
Protected Overrides Function SaveControlState() As Object
Dim state As Object = MyBase.SaveControlState()
If Me.SelectedIndex >= 0 Then
If state IsNot Nothing Then
Return New Pair(state, Me.SelectedIndex)
Else
Return Me.SelectedIndex
End If
Else
Return state
End If
End Function
Protected Overrides Sub LoadControlState(ByVal state As Object)
If state IsNot Nothing Then
Dim p As Pair = TryCast(state, Pair)
If p IsNot Nothing Then
MyBase.LoadControlState(p.First)
_SelectedIndex = CInt(p.Second)
Else
If (TypeOf (state) Is Integer) Then
_SelectedIndex = CInt(state)
Else
MyBase.LoadControlState(state)
End If
End If
End If
MyBase.SelectedIndex = _SelectedIndex
End Sub
End Class