Solved

DropdownList items are cleared on postback

Posted on 2009-05-05
1
893 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
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

706 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now