I think I understand ViewState pretty well, but the following is giving me some troubles:
From http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx
Postback controls such as dropdownlist and textbox restore their posted state (the selected item of a dropdown ist 'posted') even when ViewState is disabled, because even with ViewState disabled the control is still able to post its value
Assuming DropDownList has EnableViewState set to false, then ( according to the above quote ) when user issues a postback by selecting an item in DropDownList, the following code should result in Label1.Text displaying a value of a selected item ( thus DropDownList.SelectedValue should return a value selected by user, even if viewstate is disabled ), but instead I get an empty string:
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
}
}
The author of that article appears to be an expert on the subject, so I'm assuming I'm doing something wrong !?!
thanx
There is no selected value because:
1) there are no items in the drop down list, because you are only binding the data to it the first time around. Normally this is good practice, but when you have ViewState turned off, you must explicitly re-create the data for the control every time.
2) You are binding the data after the point in the page lifecycle where the Request dictionary values are applied to controls (namely, during the restoration of ViewState to controls.) The posted value exists in the Request dictionary, but since there are no items in the dropdownlist, it can't really do much with it. Even though ViewState is turned off, your author is correct - the posted value will be applied, at the point in the lifecycle where ViewState would normally be applied.
If you were to re-create the data for the list in Init(), then the dropdown would be populated for the posted value to be applied to, it would be applied, and the selected value would be available by the time you got to Load(). Hopefully that's clear. Some working code is below:
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();
}
}
Here's a much smarter DropDownList implementation. Not to troll or anything, but I can't believe how limited (read: stupid) some of the ASP.Net controls are....
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With