Solved

DropdownList items are cleared on postback

Posted on 2009-05-05
1
902 Views
Last Modified: 2013-12-17
Hi,

I have created a custom dropdownlist that gets its values from a datasource (database).
My problem exists, when the page is posted back to itself - the items in the list are not persisted.

In my code, I can see why this happens - it is because I am not refilling the list automatically on postback (common practice).
However, how does the list refill itself.


     Q: Are the items in the list, supposed to be maintained across postback (must I call some methods like CreateChildControls)????
     Q: Do I have to rebind the list in the lists SelectedIndexChanged event handler (like you would with a GridView/DataList etc)????


This has been an issue for sometime now - to resolve it, I have just removed the !Page.IsPostBack condition (however, as this suggests, the code gets run when leaving pages etc which is inefficient - this is the main reason for it being there).

Hopefully, this is a 101 question - and I have missed this lesson early in my career.

Any help appreciated - thanks for your time.

Cheers.

using System;
using System.Web.UI.WebControls;
using System.Collections;
using System.ComponentModel;
 
namespace MWeb.Web.UI.WebControls
{
	/// <summary>
	/// Base Class for Extra Item <code>DropDownList</code>s
	/// </summary>
	abstract public class ExtraItemDropDownList : System.Web.UI.WebControls.DropDownList, IExtraItemList
    {
        #region Declarations
 
        #region Constants
 
        public const string DEFAULT_EXTRAITEM_TEXT = "None";
		public const string DEFAULT_EXTRAITEM_VALUE = "0";
 
		public const string DEFAULT_DATATEXT_FIELD = "DataTextField";
		public const string DEFAULT_DATAVALUE_FIELD = "DataValueField";
 
        public const int DEFAULT_CACHE_TIME_IN_MINS = 0;
 
		#endregion
 
        #region Member Variables
 
        //private bool _hasDataBind = false;
 
        #endregion
 
        #endregion
 
        #region Constructor
 
        public ExtraItemDropDownList():
                base()
		{
            this.Init += new EventHandler(this.Control_Init);
            this.Load += new EventHandler(this.Control_Load);
            this.PreRender += new EventHandler(this.Control_PreRender);
        }   
 
		#endregion
 
		#region Abstract and Virtuals
 
		protected abstract void Fill();
		public virtual void Refresh()
		{
            //clear all items.
            this.Items.Clear();
 
            //refill.
            this.Fill();
 
            //clean data.
            this.IsDirtyData = false;
		}
 
		#endregion
 
		#region Control Events
 
		///<summary>
		///Fills the DropDownList with items from the database on the first request
		///If PopulateOnLoad is true. Will populate itself on any request where
		///IsDirtyData is true.
        ///</summary>       
        private void Control_Init(object sender, System.EventArgs e)
        {
            if ((!Page.IsPostBack && this.PopulateOnLoad) || this.IsDirtyData)
            {
                this.Refresh(); ////////////////*************THIS IS NOT EXECUTED ON POSTBACK (AS EXPECTED) - BUT IT FILLS THE LIST!!!! QUESTION: Are the list items suppossed to be maintained across postback or am I supposed to rebind the list!
            }
        }
 
        private void Control_Load(object sender, System.EventArgs e)
        {
 
        }
 
        private void Control_PreRender(object sender, System.EventArgs e)
        {
            //disable if only single item.
            if (this.DisableSingleItem && this.Enabled)
            {//must already be enabled!
 
                this.Enabled = this.IncludeExtraItem ? (this.Items.Count > 2) : (this.Items.Count > 1);
            }
 
            //remove excluded values.
            if (!string.IsNullOrEmpty(this.ExcludedValueList))
            {
                string[] excludedValues = this.ExcludedValueList.Split(new char[] { ',', ' ' });
                foreach (string excludedValue in excludedValues)
                {
                    this.Items.Remove(this.Items.FindByValue(excludedValue));
                }
            }
        }
 
        public override void DataBind()
        {
            //bind data.
            //try
            //{
                //base.DataBind();
            //}
            //catch { ;} //TODO: THIS IS A HACK - a selected index exception was being thrown when I was filtering/refreshing lists. Couldnt find a solution so this was a temp fix.
 
            //create new list item
            if (this.IncludeExtraItem)
            {
                ListItem newItem = new ListItem();
                newItem.Text = this.ExtraItemText;
                newItem.Value = this.ExtraItemValue;
                newItem.Selected = false;
 
                //add list item to specified position
                if ((this.ExtraItemPosition == ExtraItemPosition.Top || this.ExtraItemPosition == ExtraItemPosition.Start))
                {
                    this.Items.Insert(0, newItem);
                }
                else if ((ExtraItemPosition == ExtraItemPosition.Bottom || this.ExtraItemPosition == ExtraItemPosition.End))
                {
                    this.Items.Add(newItem);
                }
            }
 
            // now select the default item
            if (this.InitialValue.ToString().Length > 0)
            {
                for (int i = 0; i < this.Items.Count;i++)
                {
                    ListItem li = this.Items[i];
                    if (li.Value == this.InitialValue)
                    {
                        if (!li.Selected)
                            li.Selected = true;
                        break;
                    }
                }
            }
 
            //set binded flag.
            //this._hasDataBind = true;
        }		
		
		#endregion
 
		#region Properties
 
        [Description("Sets the cache time in minutes for the list."), Category("Loading")]
        public int CacheTimeInMins
        {
            get
            {
                if (this.ViewState["CacheTimeInMins"] == null)
                {
                    this.ViewState["CacheTimeInMins"] = DEFAULT_CACHE_TIME_IN_MINS;
                }
                return (int)this.ViewState["CacheTimeInMins"];
            }
            set
            {
                this.ViewState["CacheTimeInMins"] = value;
            }
        }
 
        [Description("If you set this value to true before the Load event occurs then the control will reload its self."), Category("Loading")]
        public bool IsDirtyData
        {
            get
            {
                if (this.ViewState["IsDirtyData"] == null)
                {
                    this.ViewState["IsDirtyData"] = false;
                }
                return (bool)this.ViewState["IsDirtyData"];
            }
            set
            {
                this.ViewState["IsDirtyData"] = value;
            }
        }
 
        [Description("If you set this value to true then this control will pre-populate itself when it loads."), Category("Loading")]
        public bool PopulateOnLoad
        {
            get
            {
                if (this.ViewState["PopulateOnLoad"] == null)
                {
                    this.ViewState["PopulateOnLoad"] = true;
                }
                return (bool)this.ViewState["PopulateOnLoad"];
            }
            set
            {
                this.ViewState["PopulateOnLoad"] = value;
            }
        }
 
        [Description("The value of the initially selected item"), Category("Data")]
        public string InitialValue
        {
            get
            {
                if (this.ViewState["InitialValue"] == null)
                {
                    this.ViewState["InitialValue"] = string.Empty;
                }
                return (string)this.ViewState["InitialValue"];
            }
 
            set
            {
                this.ViewState["InitialValue"] = value;
            }
        }
 
		[Description("bool:  Include extra item in list?"),Category("Extra")]
		public bool IncludeExtraItem
		{
			get
			{
				if(this.ViewState["IncludeExtraItem"]==null)
				{
					this.ViewState["IncludeExtraItem"] = false;
				}
				return (bool) this.ViewState["IncludeExtraItem"];
			}
			set
			{
				this.ViewState["IncludeExtraItem"] = value;
			}
		}
 
		[Description("bool:  Should the extra item always been shown at the top of the list"),Category("Extra")]
		public ExtraItemPosition ExtraItemPosition
		{
			get
			{
				if(this.ViewState["ExtraItemPosition"]==null)
				{
					this.ViewState["ExtraItemPosition"] = ExtraItemPosition.Top;
				}
				return (ExtraItemPosition) this.ViewState["ExtraItemPosition"];
			}
			set
			{
				this.ViewState["ExtraItemPosition"] = value;
			}
		}
 
		[Description("string:  The text string displayed for extra item"),Category("Extra")]
		public string ExtraItemText
		{
			get
			{
				if(this.ViewState["ExtraItemText"]==null)
				{
					this.ViewState["ExtraItemText"] = string.Empty;
				}
				return (string) this.ViewState["ExtraItemText"];
			}
			set
			{
				this.ViewState["ExtraItemText"] = value;
			}
		}		
 
		[Description("string:  The value used for the extra item"),Category("Extra")]
		public string ExtraItemValue
		{
			get
			{
                if (this.ViewState["ExtraItemValue"] == null)
				{
                    this.ViewState["ExtraItemValue"] = string.Empty;
				}
                return (string)this.ViewState["ExtraItemValue"];
			}
			set
			{
                this.ViewState["ExtraItemValue"] = value;
			}
        }
 
        [Description("If you set this to true, the list will disabled when their is only one item in the list."), Category("Loading")]
        public bool DisableSingleItem
        {
            get
            {
                if (this.ViewState["DisableSingleItem"] == null)
                {
                    this.ViewState["DisableSingleItem"] = true;
                }
                return (bool)this.ViewState["DisableSingleItem"];
            }
            set
            {
                this.ViewState["DisableSingleItem"] = value;
            }
        }
 
        [Description("Excludes the values specified from list."), Category("Loading")]
        public string ExcludedValueList
        {
            get
            {
                return (string)this.ViewState["ExcludedValueList"];
            }
            set
            {
                this.ViewState["ExcludedValueList"] = value;
            }
        }
	
		#endregion
 
	}
}

Open in new window

0
Comment
Question by:smacca
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 
LVL 6

Accepted Solution

by:
M3mph15 earned 500 total points
ID: 24311008
Hi,

Any controls of list items that are created dynamically, so if your binding the Datasource to the DropDownList in your code behind then you will need to bind them at every postback.
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question