Why does DropDownList.SelectedValue is relied on viewstate?

后端 未结 4 486
南方客
南方客 2021-02-08 22:01

If I set on my page : EnableViewState=\"true\" ViewStateMode=\"Disabled\" - Then - the Viewstate is disable for the page ( unless override...)

The

相关标签:
4条回答
  • 2021-02-08 22:18

    The SelectedValue relies on ViewState because on PostBack it rebuilds its ListItems from the ViewState and then sets the selected value on the DropDownList from the Request Object.

    It is not taking the Request value as the SelectedValue directly. This in turn is because, ASP.Net can check if the posted DropDownList has not been tampered with at the client. It does so by first de-serializing the original items from the ViewState. It then finds the Request Value in the items and sets its Selected property as true. Only now, the SelectedValue property is available. (or SelectedIndex for that matter). It should be able to fire a SelectedIndexChanged event now.

    This is also the reason that you do not need to bind the DropDownList again in PageLoad. The list items are automagically retreived from the ViewState.

    If the ViewState is disabled, then there will be no original list items in the ViewState and will be empty. Hence it will not be able to mark any item as selected. Hence the SelectedValue will be 0 or the SelectedItem will be null. I think the SelectedIndexChanged event will also not fire. For things to work in this case databinding needs to be done, preferably on init.

    There are workarounds to that however.

    Complete Reference: http://msdn.microsoft.com/en-us/library/ms972976.aspx

    Edit: (after Op's comments)

    Following the page life cycle to see where SelectedValue relies on ViewState:

    Stage 1 Init: The control heirarchy is built. If the DropDownList is bound here or the ListItems have been added declaratively, the List gets populated here.

    Stage 2 Load ViewState: On PostBack, the ViewState is validated here and loaded into the DropDownList. There is no SelectedValue here.

    Stage 3 Load PostBack Data: Here the Request Value (from the form request) is taken and then applied to the control. In this case of DropDownList it now sets the SelectedValue from the received Request Object Value, internal implementation is something like this:

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

    What is important here is that if ViewState is not there and DropDownList is not data-bound, then the ListItem collection will be empty and hence SelectedValue property is 0. This has nothing to do with internal implementation of a property.

    If the ViewState is not there (disabled) and DropDownList is data-bound, then the ListItem collection will exist and corresponding item will be marked as selected and hence SelectedValue property will return the correct value.

    If the item collection is new (thru a re-binding with different data set or ViewState is invalidated), then the Request Form value would not be found in the item collection and again SelectedValue will be invalid.

    Stage 4 Page Load: by this time the ViewState (or data-binding) and PostBack Data has already been loaded.

    Stage 5 Raise PostBack Event: At this stage the OnSelectedIndexChanged event of DropDownList is fired if the index was changed in Stage 3.

    Hence, the SelectedValue relies on ViewState at Stage 3. Of course, if the control is appropriately data-bound then it will not rely on ViewState as a corollary.

    SelectedValue relies on ViewState to make sure the items collection has been populated prior to setting it. Data-binding / Re-binding is just another way to make sure the items collection is populated.

    Hope that clarifies.

    0 讨论(0)
  • 2021-02-08 22:23

    SUMMARY: If you want the control to work without ViewState, you need to populate/bind the Items collection on every postback. I recommend doing it in the Page_Init event (i.e. OnInit method).

    First off, I always recommend this this awesome article: TRULY Understanding ViewState.

    The SelectedValue doesn't require ViewState. Looking at the code for ListControl, which DropDownList inherits from, we see the code:

    public virtual string SelectedValue
    {
      get
      {
        int selectedIndex = this.SelectedIndex;
        if (selectedIndex >= 0)
          return this.Items[selectedIndex].Value;
        else
          return string.Empty;
      }
    

    The important thing to take away from this code is that the Items list must be populated to get the SelectedValue.

    If you utilize ViewState, the Items collection is persisted to / loaded from ViewState, which allows the SelectedValue property to work without rebinding the control.

    0 讨论(0)
  • 2021-02-08 22:36
          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"];
        }
    
    0 讨论(0)
  • 2021-02-08 22:38

    If you want the DropDownList to work without ViewState, you can bind the control in page_load only once as given below:

         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 ; //
                }           
    
    • In the case ( ViewState is disabled), Asp.net FrameWork retrieve the items from the back end with every PostBack.

    • In the case (ViewState is enabled), Asp.net FrameWork retrieve the items from the ViewState without hitting the back end with every PostBack

    Normally, the Asp.net FrameWork fire the data binding events in PreRender event: Read ASP.NET Page Life Cycle Overview

    You can confirm that behavior by enabling Trace.

    SelectedValue doesn't rely directly on ViewState from source code of ListControl , BUT depend on items as described above.

    0 讨论(0)
提交回复
热议问题