2009-06-07 21 views
8

我想我明白的ViewState很好,但下面是給我一些麻煩:即使DropDownList中有viestate禁用的SelectedValue還是應該返回一個值

http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx

回傳控制例如下拉列表和文本框即使在ViewState被禁用時恢復其發佈狀態(所選項目的下拉列表「已發佈」),因爲即使禁用了ViewState,控件仍然能夠發佈其值


假設的DropDownList的EnableViewState設置爲假,則(根據上面的引用)當用戶通過在DropDownList中選擇項目發出一個回傳,下面的代碼應導致Label1的。文本顯示所選擇的項目(因此DropDownList.SelectedValue應該返回由用戶選擇的值,即使視圖狀態被禁用)的值,而是我得到一個空字符串:

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 
    } 
} 


那篇文章的作者似乎是這方面的專家,所以我假設我做錯了什麼!?!


感謝名單

+1

你看到什麼時候你檢查請求[DropDownList1.ClientID]在回發? – 2009-06-07 21:55:54

+0

回發請求[DropDownList1。ClientID]確實返回選定的值 – SourceC 2009-06-07 22:57:25

回答

17

沒有選擇的價值,因爲:

1)有在下拉列表中沒有的項目,因爲你只有數據第一次就綁定到它。通常這是一個很好的做法,但是當您關閉ViewState時,您必須每次都明確地重新創建控件的數據。

2)綁定頁面生命週期中將請求字典值應用於控件(即將ViewState恢復爲控件期間)後的數據。發佈的值存在於請求字典中,但自下拉列表中沒有任何項目,但它無法真正做到。即使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

這裏有一個更聰明的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 
相關問題