Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / UI / HtmlControls / HtmlSelect.cs / 1 / HtmlSelect.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.UI.HtmlControls { using System.Runtime.Serialization.Formatters; using System.Text; using System.ComponentModel; using System; using System.Collections; using System.Collections.Specialized; using System.Data; using System.Web; using System.Web.Util; using System.Web.UI; using System.Web.UI.WebControls; using System.Globalization; using Debug=System.Web.Util.Debug; using System.Security.Permissions; [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class HtmlSelectBuilder : ControlBuilder { public override Type GetChildControlType(string tagName, IDictionary attribs) { if (StringUtil.EqualsIgnoreCase(tagName, "option")) return typeof(ListItem); return null; } public override bool AllowWhitespaceLiterals() { return false; } } ////// [ DefaultEvent("ServerChange"), ValidationProperty("Value"), ControlBuilderAttribute(typeof(HtmlSelectBuilder)), SupportsEventValidation, ] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class HtmlSelect : HtmlContainerControl, IPostBackDataHandler, IParserAccessor { private static readonly object EventServerChange = new object(); internal const string DataBoundViewStateKey = "_!DataBound"; private object dataSource; private ListItemCollection items; private int cachedSelectedIndex; private bool _requiresDataBinding; private bool _inited; private bool _throwOnDataPropertyChange; private DataSourceView _currentView; private bool _currentViewIsFromDataSourceID; private bool _currentViewValid; private bool _pagePreLoadFired; /* * Creates an intrinsic Html SELECT control. */ public HtmlSelect() : base("select") { cachedSelectedIndex = -1; } ////// The ////// class defines the methods, properties, and events for the /// HtmlSelect control. This class allows programmatic access to the HTML /// <select> element on the server. /// /// [ DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), WebCategory("Data"), WebSysDescription(SR.HtmlSelect_DataMember) ] public virtual string DataMember { get { object o = ViewState["DataMember"]; if (o != null) return (string)o; return String.Empty; } set { Attributes["DataMember"] = MapStringAttributeToString(value); OnDataPropertyChanged(); } } ///[To be supplied.] ////// Gets or sets the data source to databind the list values /// in the [ WebCategory("Data"), DefaultValue(null), WebSysDescription(SR.BaseDataBoundControl_DataSource), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public virtual object DataSource { get { return dataSource; } set { if ((value == null) || (value is IListSource) || (value is IEnumerable)) { dataSource = value; OnDataPropertyChanged(); } else { throw new ArgumentException(SR.GetString(SR.Invalid_DataSource_Type, ID)); } } } ///control against. This provides data to /// populate the select list with items. /// /// The ID of the DataControl that this control should use to retrieve /// its data source. When the control is bound to a DataControl, it /// can retrieve a data source instance on-demand, and thereby attempt /// to work in auto-DataBind mode. /// [ DefaultValue(""), WebCategory("Data"), WebSysDescription(SR.BaseDataBoundControl_DataSourceID), ] public virtual string DataSourceID { get { object o = ViewState["DataSourceID"]; if (o != null) { return (string)o; } return String.Empty; } set { ViewState["DataSourceID"] = value; OnDataPropertyChanged(); } } ////// [ WebCategory("Data"), DefaultValue(""), WebSysDescription(SR.HtmlSelect_DataTextField) ] public virtual string DataTextField { get { string s = Attributes["DataTextField"]; return((s == null) ? String.Empty : s); } set { Attributes["DataTextField"] = MapStringAttributeToString(value); if (_inited) { RequiresDataBinding = true; } } } ////// Gets or sets the field in the data source that provides /// the text for an option entry in the HtmlSelect control. /// ////// [ WebCategory("Data"), DefaultValue(""), WebSysDescription(SR.HtmlSelect_DataValueField) ] public virtual string DataValueField { get { string s = Attributes["DataValueField"]; return((s == null) ? String.Empty : s); } set { Attributes["DataValueField"] = MapStringAttributeToString(value); if (_inited) { RequiresDataBinding = true; } } } ////// Gets or sets the field in the data source that provides /// the option item value for the ////// control. /// /// public override string InnerHtml { get { throw new NotSupportedException(SR.GetString(SR.InnerHtml_not_supported, this.GetType().Name)); } set { throw new NotSupportedException(SR.GetString(SR.InnerHtml_not_supported, this.GetType().Name)); } } ///[To be supplied.] ////// public override string InnerText { get { throw new NotSupportedException(SR.GetString(SR.InnerText_not_supported, this.GetType().Name)); } set { throw new NotSupportedException(SR.GetString(SR.InnerText_not_supported, this.GetType().Name)); } } protected bool IsBoundUsingDataSourceID { get { return (DataSourceID.Length > 0); } } /* * A collection containing the list of items. */ ///[To be supplied.] ////// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ] public ListItemCollection Items { get { if (items == null) { items = new ListItemCollection(); if (IsTrackingViewState) ((IStateManager)items).TrackViewState(); } return items; } } /* * Multi-select property. */ ////// Gets the list of option items in an ///control. /// /// [ WebCategory("Behavior"), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public bool Multiple { get { string s = Attributes["multiple"]; return((s != null) ? (s.Equals("multiple")) : false); } set { if (value) Attributes["multiple"] = "multiple"; else Attributes["multiple"] = null; } } /* * Name property. */ [ WebCategory("Behavior"), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public string Name { get { return UniqueID; //string s = Attributes["name"]; //return ((s != null) ? s : ""); } set { //Attributes["name"] = MapStringAttributeToString(value); } } // Value that gets rendered for the Name attribute internal string RenderedNameAttribute { get { return Name; //string name = Name; //if (name.Length == 0) // return UniqueID; //return name; } } protected bool RequiresDataBinding { get { return _requiresDataBinding; } set { _requiresDataBinding = value; } } /* * The index of the selected item. * Returns the first selected item if list is multi-select. * Returns -1 if there is no selected item. */ ////// Gets or sets a value indicating whether multiple option items can be selected /// from the list. /// ////// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), HtmlControlPersistable(false), ] public virtual int SelectedIndex { get { for (int i=0; i < Items.Count; i++) { if (Items[i].Selected) return i; } if (Size <= 1 && !Multiple) { // SELECT as a dropdown must have a selection if (Items.Count > 0) Items[0].Selected = true; return 0; } return -1; } set { // if we have no items, save the selectedindex // for later databinding if (Items.Count == 0) { cachedSelectedIndex = value; } else { if (value < -1 || value >= Items.Count) { throw new ArgumentOutOfRangeException("value"); } ClearSelection(); if (value >= 0) Items[value].Selected = true; } } } /* * SelectedIndices property. * Protected property for getting array of selected indices. */ ////// Gets or sets the ordinal index of the selected option item in an /// ///control. If multiple items are selected, this /// property holds the index of the first item selected in the list. /// /// /// protected virtual int[] SelectedIndices { get { int n = 0; int[] temp = new int[3]; for (int i=0; i < Items.Count; i++) { if (Items[i].Selected == true) { if (n == temp.Length) { int[] t = new int[n+n]; temp.CopyTo(t,0); temp = t; } temp[n++] = i; } } int[] selectedIndices = new int[n]; Array.Copy(temp,0,selectedIndices,0,n); return selectedIndices; } } /* * The size of the list. * A size of 1 displays a dropdown list. */ ////// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public int Size { get { string s = Attributes["size"]; return((s != null) ? Int32.Parse(s, CultureInfo.InvariantCulture) : -1); } set { Attributes["size"] = MapIntegerAttributeToString(value); } } /* * Value property. */ ////// Gets or sets the number of option items visible in the browser at a time. A /// value greater that one will typically cause browsers to display a scrolling /// list. /// ////// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public string Value { get { int i = SelectedIndex; return(i < 0 || i >= Items.Count) ? String.Empty : Items[i].Value; } set { int i = Items.FindByValueInternal(value, true); if (i >= 0) SelectedIndex = i; } } ////// Gets or sets the current item selected in the ////// control. /// /// [ WebCategory("Action"), WebSysDescription(SR.HtmlSelect_OnServerChange) ] public event EventHandler ServerChange { add { Events.AddHandler(EventServerChange, value); } remove { Events.RemoveHandler(EventServerChange, value); } } ////// Occurs when an ///control is changed on the /// server. /// protected override void AddParsedSubObject(object obj) { if (obj is ListItem) Items.Add((ListItem)obj); else throw new HttpException(SR.GetString(SR.Cannot_Have_Children_Of_Type, "HtmlSelect", obj.GetType().Name)); } /// /// /// protected virtual void ClearSelection() { for (int i=0; i < Items.Count; i++) Items[i].Selected = false; } ////// Connects this data bound control to the appropriate DataSourceView /// and hooks up the appropriate event listener for the /// DataSourceViewChanged event. The return value is the new view (if /// any) that was connected to. An exception is thrown if there is /// a problem finding the requested view or data source. /// private DataSourceView ConnectToDataSourceView() { if (_currentViewValid && !DesignMode) { // If the current view is correct, there is no need to reconnect return _currentView; } // Disconnect from old view, if necessary if ((_currentView != null) && (_currentViewIsFromDataSourceID)) { // We only care about this event if we are bound through the DataSourceID property _currentView.DataSourceViewChanged -= new EventHandler(OnDataSourceViewChanged); } // Connect to new view IDataSource ds = null; string dataSourceID = DataSourceID; if (dataSourceID.Length != 0) { // Try to find a DataSource control with the ID specified in DataSourceID Control control = DataBoundControlHelper.FindControl(this, dataSourceID); if (control == null) { throw new HttpException(SR.GetString(SR.DataControl_DataSourceDoesntExist, ID, dataSourceID)); } ds = control as IDataSource; if (ds == null) { throw new HttpException(SR.GetString(SR.DataControl_DataSourceIDMustBeDataControl, ID, dataSourceID)); } } if (ds == null) { // DataSource control was not found, construct a temporary data source to wrap the data ds = new ReadOnlyDataSource(DataSource, DataMember); } else { // Ensure that both DataSourceID as well as DataSource are not set at the same time if (DataSource != null) { throw new InvalidOperationException(SR.GetString(SR.DataControl_MultipleDataSources, ID)); } } // IDataSource was found, extract the appropriate view and return it DataSourceView newView = ds.GetView(DataMember); if (newView == null) { throw new InvalidOperationException(SR.GetString(SR.DataControl_ViewNotFound, ID)); } _currentViewIsFromDataSourceID = IsBoundUsingDataSourceID; _currentView = newView; if ((_currentView != null) && (_currentViewIsFromDataSourceID)) { // We only care about this event if we are bound through the DataSourceID property _currentView.DataSourceViewChanged += new EventHandler(OnDataSourceViewChanged); } _currentViewValid = true; return _currentView; } protected override ControlCollection CreateControlCollection() { return new EmptyControlCollection(this); } protected void EnsureDataBound() { try { _throwOnDataPropertyChange = true; if (RequiresDataBinding && DataSourceID.Length > 0) { DataBind(); } } finally{ _throwOnDataPropertyChange = false; } } ////// Returns an IEnumerable that is the DataSource, which either came /// from the DataSource property or from the control bound via the /// DataSourceID property. /// protected virtual IEnumerable GetData() { DataSourceView view = ConnectToDataSourceView(); Debug.Assert(_currentViewValid); if (view != null) { return view.ExecuteSelect(DataSourceSelectArguments.Empty); } return null; } /* * Override to load items and selected indices. */ ////// /// protected override void LoadViewState(object savedState) { if (savedState != null) { Triplet statetriplet = (Triplet)savedState; base.LoadViewState(statetriplet.First); // restore state of items ((IStateManager)Items).LoadViewState(statetriplet.Second); // restore selected indices object selectedIndices = statetriplet.Third; if (selectedIndices != null) Select((int[])selectedIndices); } } ////// /// protected override void OnDataBinding(EventArgs e) { base.OnDataBinding(e); // create items using the datasource IEnumerable dataSource = GetData(); // create items using the datasource if (dataSource != null) { bool fieldsSpecified = false; string textField = DataTextField; string valueField = DataValueField; Items.Clear(); ICollection collection = dataSource as ICollection; if (collection != null) { Items.Capacity = collection.Count; } if ((textField.Length != 0) || (valueField.Length != 0)) fieldsSpecified = true; foreach (object dataItem in dataSource) { ListItem item = new ListItem(); if (fieldsSpecified) { if (textField.Length > 0) { item.Text = DataBinder.GetPropertyValue(dataItem,textField,null); } if (valueField.Length > 0) { item.Value = DataBinder.GetPropertyValue(dataItem,valueField,null); } } else { item.Text = item.Value = dataItem.ToString(); } Items.Add(item); } } // try to apply the cached SelectedIndex now if (cachedSelectedIndex != -1) { SelectedIndex = cachedSelectedIndex; cachedSelectedIndex = -1; } ViewState[DataBoundViewStateKey] = true; RequiresDataBinding = false; } ////// This method is called when DataMember, DataSource, or DataSourceID is changed. /// protected virtual void OnDataPropertyChanged() { if (_throwOnDataPropertyChange) { throw new HttpException(SR.GetString(SR.DataBoundControl_InvalidDataPropertyChange, ID)); } if (_inited) { RequiresDataBinding = true; } _currentViewValid = false; } protected virtual void OnDataSourceViewChanged(object sender, EventArgs e) { RequiresDataBinding = true; } protected internal override void OnInit(EventArgs e) { base.OnInit(e); if (Page != null) { Page.PreLoad += new EventHandler(this.OnPagePreLoad); if (!IsViewStateEnabled && Page.IsPostBack) { RequiresDataBinding = true; } } } protected internal override void OnLoad(EventArgs e) { _inited = true; // just in case we were added to the page after PreLoad ConnectToDataSourceView(); if (Page != null && !_pagePreLoadFired && ViewState[DataBoundViewStateKey] == null) { // If the control was added after PagePreLoad, we still need to databind it because it missed its // first change in PagePreLoad. If this control was created by a call to a parent control's DataBind // in Page_Load (with is relatively common), this control will already have been databound even // though pagePreLoad never fired and the page isn't a postback. if (!Page.IsPostBack) { RequiresDataBinding = true; } // If the control was added to the page after page.PreLoad, we'll never get the event and we'll // never databind the control. So if we're catching up and Load happens but PreLoad never happened, // call DataBind. This may make the control get databound twice if the user called DataBind on the control // directly in Page.OnLoad, but better to bind twice than never to bind at all. else if (IsViewStateEnabled) { RequiresDataBinding = true; } } base.OnLoad(e); } private void OnPagePreLoad(object sender, EventArgs e) { _inited = true; if (Page != null) { Page.PreLoad -= new EventHandler(this.OnPagePreLoad); // Setting RequiresDataBinding to true in OnLoad is too late because the OnLoad page event // happens before the control.OnLoad method gets called. So a page_load handler on the page // that calls DataBind won't prevent DataBind from getting called again in PreRender. if (!Page.IsPostBack) { RequiresDataBinding = true; } // If this is a postback and viewstate is enabled, but we have never bound the control // before, it is probably because its visibility was changed in the postback. In this // case, we need to bind the control or it will never appear. This is a common scenario // for Wizard and MultiView. if (Page.IsPostBack && IsViewStateEnabled && ViewState[DataBoundViewStateKey] == null) { RequiresDataBinding = true; } } _pagePreLoadFired = true; } /* * This method is invoked just prior to rendering. */ ////// /// protected internal override void OnPreRender(EventArgs e) { base.OnPreRender(e); // An Html SELECT does not post when nothing is selected. if (Page != null && !Disabled) { if (Size > 1) { Page.RegisterRequiresPostBack(this); } Page.RegisterEnabledControl(this); } EnsureDataBound(); } /* * Method used to raise the OnServerChange event. */ ////// protected virtual void OnServerChange(EventArgs e) { EventHandler handler = (EventHandler)Events[EventServerChange]; if (handler != null) handler(this, e); } /* * Override to prevent SelectedIndex from being rendered as an attribute. */ ////// Raised /// on the server when the ///control list values /// change between postback requests. /// /// /// protected override void RenderAttributes(HtmlTextWriter writer) { if (Page != null) { Page.ClientScript.RegisterForEventValidation(RenderedNameAttribute); } writer.WriteAttribute("name", RenderedNameAttribute); Attributes.Remove("name"); Attributes.Remove("DataValueField"); Attributes.Remove("DataTextField"); Attributes.Remove("DataMember"); Attributes.Remove("DataSourceID"); base.RenderAttributes(writer); } /* * Render the Items in the list. */ ////// /// protected internal override void RenderChildren(HtmlTextWriter writer) { bool selected = false; bool isSingle = !Multiple; writer.WriteLine(); writer.Indent++; ListItemCollection liCollection = Items; int n = liCollection.Count; if (n > 0) { for (int i=0; i < n; i++) { ListItem li = liCollection[i]; writer.WriteBeginTag("option"); if (li.Selected) { if (isSingle) { if (selected) throw new HttpException(SR.GetString(SR.HtmlSelect_Cant_Multiselect_In_Single_Mode)); selected=true; } writer.WriteAttribute("selected", "selected"); } writer.WriteAttribute("value", li.Value, true /*fEncode*/); // This is to fix the case where the user puts one of these // three values in the AttributeCollection. Removing them // at least is better than rendering them twice. li.Attributes.Remove("text"); li.Attributes.Remove("value"); li.Attributes.Remove("selected"); li.Attributes.Render(writer); writer.Write(HtmlTextWriter.TagRightChar); HttpUtility.HtmlEncode(li.Text, writer); writer.WriteEndTag("option"); writer.WriteLine(); } } writer.Indent--; } /* * Save selected indices and modified Items. */ ////// /// protected override object SaveViewState() { object baseState = base.SaveViewState(); object items = ((IStateManager)Items).SaveViewState(); object selectedindices = null; // only save selection if handler is registered, // we are disabled, or we are not visible // since selection is always posted back otherwise if (Events[EventServerChange] != null || Disabled || !Visible) selectedindices = SelectedIndices; if (selectedindices != null || items != null || baseState != null) return new Triplet(baseState, items, selectedindices); return null; } ////// /// protected virtual void Select(int[] selectedIndices) { ClearSelection(); for (int i=0; i < selectedIndices.Length; i++) { int n = selectedIndices[i]; if (n >= 0 && n < Items.Count) Items[n].Selected = true; } } /* * TrackState */ ////// /// protected override void TrackViewState() { base.TrackViewState(); ((IStateManager)Items).TrackViewState(); } /* * Method of IPostBackDataHandler interface to process posted data. * SelectList processes a newly posted value. */ ////// /// bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { return LoadPostData(postDataKey, postCollection); } ////// /// protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) { string[] selectedItems = postCollection.GetValues(postDataKey); bool selectionChanged = false; if (selectedItems != null) { if (!Multiple) { int n = Items.FindByValueInternal(selectedItems[0], false); if (SelectedIndex != n) { SelectedIndex = n; selectionChanged = true; } } else { // multiple selection int count = selectedItems.Length; int[] oldSelectedIndices = SelectedIndices; int[] newSelectedIndices = new int[count]; for (int i=0; i < count; i++) { // create array of new indices from posted values newSelectedIndices[i] = Items.FindByValueInternal(selectedItems[i], false); } if (oldSelectedIndices.Length == count) { // check new indices against old indices // assumes selected values are posted in order for (int i=0; i < count; i++) { if (newSelectedIndices[i] != oldSelectedIndices[i]) { selectionChanged = true; break; } } } else { // indices must have changed if count is different selectionChanged = true; } if (selectionChanged) { // select new indices Select(newSelectedIndices); } } } else { // no items selected if (SelectedIndex != -1) { SelectedIndex = -1; selectionChanged = true; } } if (selectionChanged) { ValidateEvent(postDataKey); } return selectionChanged; } /* * Method of IPostBackDataHandler interface which is invoked whenever posted data * for a control has changed. SelectList fires an OnServerChange event. */ ////// /// void IPostBackDataHandler.RaisePostDataChangedEvent() { RaisePostDataChangedEvent(); } ////// /// protected virtual void RaisePostDataChangedEvent() { OnServerChange(EventArgs.Empty); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.UI.HtmlControls { using System.Runtime.Serialization.Formatters; using System.Text; using System.ComponentModel; using System; using System.Collections; using System.Collections.Specialized; using System.Data; using System.Web; using System.Web.Util; using System.Web.UI; using System.Web.UI.WebControls; using System.Globalization; using Debug=System.Web.Util.Debug; using System.Security.Permissions; [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class HtmlSelectBuilder : ControlBuilder { public override Type GetChildControlType(string tagName, IDictionary attribs) { if (StringUtil.EqualsIgnoreCase(tagName, "option")) return typeof(ListItem); return null; } public override bool AllowWhitespaceLiterals() { return false; } } ////// [ DefaultEvent("ServerChange"), ValidationProperty("Value"), ControlBuilderAttribute(typeof(HtmlSelectBuilder)), SupportsEventValidation, ] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class HtmlSelect : HtmlContainerControl, IPostBackDataHandler, IParserAccessor { private static readonly object EventServerChange = new object(); internal const string DataBoundViewStateKey = "_!DataBound"; private object dataSource; private ListItemCollection items; private int cachedSelectedIndex; private bool _requiresDataBinding; private bool _inited; private bool _throwOnDataPropertyChange; private DataSourceView _currentView; private bool _currentViewIsFromDataSourceID; private bool _currentViewValid; private bool _pagePreLoadFired; /* * Creates an intrinsic Html SELECT control. */ public HtmlSelect() : base("select") { cachedSelectedIndex = -1; } ////// The ////// class defines the methods, properties, and events for the /// HtmlSelect control. This class allows programmatic access to the HTML /// <select> element on the server. /// /// [ DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), WebCategory("Data"), WebSysDescription(SR.HtmlSelect_DataMember) ] public virtual string DataMember { get { object o = ViewState["DataMember"]; if (o != null) return (string)o; return String.Empty; } set { Attributes["DataMember"] = MapStringAttributeToString(value); OnDataPropertyChanged(); } } ///[To be supplied.] ////// Gets or sets the data source to databind the list values /// in the [ WebCategory("Data"), DefaultValue(null), WebSysDescription(SR.BaseDataBoundControl_DataSource), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public virtual object DataSource { get { return dataSource; } set { if ((value == null) || (value is IListSource) || (value is IEnumerable)) { dataSource = value; OnDataPropertyChanged(); } else { throw new ArgumentException(SR.GetString(SR.Invalid_DataSource_Type, ID)); } } } ///control against. This provides data to /// populate the select list with items. /// /// The ID of the DataControl that this control should use to retrieve /// its data source. When the control is bound to a DataControl, it /// can retrieve a data source instance on-demand, and thereby attempt /// to work in auto-DataBind mode. /// [ DefaultValue(""), WebCategory("Data"), WebSysDescription(SR.BaseDataBoundControl_DataSourceID), ] public virtual string DataSourceID { get { object o = ViewState["DataSourceID"]; if (o != null) { return (string)o; } return String.Empty; } set { ViewState["DataSourceID"] = value; OnDataPropertyChanged(); } } ////// [ WebCategory("Data"), DefaultValue(""), WebSysDescription(SR.HtmlSelect_DataTextField) ] public virtual string DataTextField { get { string s = Attributes["DataTextField"]; return((s == null) ? String.Empty : s); } set { Attributes["DataTextField"] = MapStringAttributeToString(value); if (_inited) { RequiresDataBinding = true; } } } ////// Gets or sets the field in the data source that provides /// the text for an option entry in the HtmlSelect control. /// ////// [ WebCategory("Data"), DefaultValue(""), WebSysDescription(SR.HtmlSelect_DataValueField) ] public virtual string DataValueField { get { string s = Attributes["DataValueField"]; return((s == null) ? String.Empty : s); } set { Attributes["DataValueField"] = MapStringAttributeToString(value); if (_inited) { RequiresDataBinding = true; } } } ////// Gets or sets the field in the data source that provides /// the option item value for the ////// control. /// /// public override string InnerHtml { get { throw new NotSupportedException(SR.GetString(SR.InnerHtml_not_supported, this.GetType().Name)); } set { throw new NotSupportedException(SR.GetString(SR.InnerHtml_not_supported, this.GetType().Name)); } } ///[To be supplied.] ////// public override string InnerText { get { throw new NotSupportedException(SR.GetString(SR.InnerText_not_supported, this.GetType().Name)); } set { throw new NotSupportedException(SR.GetString(SR.InnerText_not_supported, this.GetType().Name)); } } protected bool IsBoundUsingDataSourceID { get { return (DataSourceID.Length > 0); } } /* * A collection containing the list of items. */ ///[To be supplied.] ////// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ] public ListItemCollection Items { get { if (items == null) { items = new ListItemCollection(); if (IsTrackingViewState) ((IStateManager)items).TrackViewState(); } return items; } } /* * Multi-select property. */ ////// Gets the list of option items in an ///control. /// /// [ WebCategory("Behavior"), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public bool Multiple { get { string s = Attributes["multiple"]; return((s != null) ? (s.Equals("multiple")) : false); } set { if (value) Attributes["multiple"] = "multiple"; else Attributes["multiple"] = null; } } /* * Name property. */ [ WebCategory("Behavior"), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public string Name { get { return UniqueID; //string s = Attributes["name"]; //return ((s != null) ? s : ""); } set { //Attributes["name"] = MapStringAttributeToString(value); } } // Value that gets rendered for the Name attribute internal string RenderedNameAttribute { get { return Name; //string name = Name; //if (name.Length == 0) // return UniqueID; //return name; } } protected bool RequiresDataBinding { get { return _requiresDataBinding; } set { _requiresDataBinding = value; } } /* * The index of the selected item. * Returns the first selected item if list is multi-select. * Returns -1 if there is no selected item. */ ////// Gets or sets a value indicating whether multiple option items can be selected /// from the list. /// ////// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), HtmlControlPersistable(false), ] public virtual int SelectedIndex { get { for (int i=0; i < Items.Count; i++) { if (Items[i].Selected) return i; } if (Size <= 1 && !Multiple) { // SELECT as a dropdown must have a selection if (Items.Count > 0) Items[0].Selected = true; return 0; } return -1; } set { // if we have no items, save the selectedindex // for later databinding if (Items.Count == 0) { cachedSelectedIndex = value; } else { if (value < -1 || value >= Items.Count) { throw new ArgumentOutOfRangeException("value"); } ClearSelection(); if (value >= 0) Items[value].Selected = true; } } } /* * SelectedIndices property. * Protected property for getting array of selected indices. */ ////// Gets or sets the ordinal index of the selected option item in an /// ///control. If multiple items are selected, this /// property holds the index of the first item selected in the list. /// /// /// protected virtual int[] SelectedIndices { get { int n = 0; int[] temp = new int[3]; for (int i=0; i < Items.Count; i++) { if (Items[i].Selected == true) { if (n == temp.Length) { int[] t = new int[n+n]; temp.CopyTo(t,0); temp = t; } temp[n++] = i; } } int[] selectedIndices = new int[n]; Array.Copy(temp,0,selectedIndices,0,n); return selectedIndices; } } /* * The size of the list. * A size of 1 displays a dropdown list. */ ////// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public int Size { get { string s = Attributes["size"]; return((s != null) ? Int32.Parse(s, CultureInfo.InvariantCulture) : -1); } set { Attributes["size"] = MapIntegerAttributeToString(value); } } /* * Value property. */ ////// Gets or sets the number of option items visible in the browser at a time. A /// value greater that one will typically cause browsers to display a scrolling /// list. /// ////// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public string Value { get { int i = SelectedIndex; return(i < 0 || i >= Items.Count) ? String.Empty : Items[i].Value; } set { int i = Items.FindByValueInternal(value, true); if (i >= 0) SelectedIndex = i; } } ////// Gets or sets the current item selected in the ////// control. /// /// [ WebCategory("Action"), WebSysDescription(SR.HtmlSelect_OnServerChange) ] public event EventHandler ServerChange { add { Events.AddHandler(EventServerChange, value); } remove { Events.RemoveHandler(EventServerChange, value); } } ////// Occurs when an ///control is changed on the /// server. /// protected override void AddParsedSubObject(object obj) { if (obj is ListItem) Items.Add((ListItem)obj); else throw new HttpException(SR.GetString(SR.Cannot_Have_Children_Of_Type, "HtmlSelect", obj.GetType().Name)); } /// /// /// protected virtual void ClearSelection() { for (int i=0; i < Items.Count; i++) Items[i].Selected = false; } ////// Connects this data bound control to the appropriate DataSourceView /// and hooks up the appropriate event listener for the /// DataSourceViewChanged event. The return value is the new view (if /// any) that was connected to. An exception is thrown if there is /// a problem finding the requested view or data source. /// private DataSourceView ConnectToDataSourceView() { if (_currentViewValid && !DesignMode) { // If the current view is correct, there is no need to reconnect return _currentView; } // Disconnect from old view, if necessary if ((_currentView != null) && (_currentViewIsFromDataSourceID)) { // We only care about this event if we are bound through the DataSourceID property _currentView.DataSourceViewChanged -= new EventHandler(OnDataSourceViewChanged); } // Connect to new view IDataSource ds = null; string dataSourceID = DataSourceID; if (dataSourceID.Length != 0) { // Try to find a DataSource control with the ID specified in DataSourceID Control control = DataBoundControlHelper.FindControl(this, dataSourceID); if (control == null) { throw new HttpException(SR.GetString(SR.DataControl_DataSourceDoesntExist, ID, dataSourceID)); } ds = control as IDataSource; if (ds == null) { throw new HttpException(SR.GetString(SR.DataControl_DataSourceIDMustBeDataControl, ID, dataSourceID)); } } if (ds == null) { // DataSource control was not found, construct a temporary data source to wrap the data ds = new ReadOnlyDataSource(DataSource, DataMember); } else { // Ensure that both DataSourceID as well as DataSource are not set at the same time if (DataSource != null) { throw new InvalidOperationException(SR.GetString(SR.DataControl_MultipleDataSources, ID)); } } // IDataSource was found, extract the appropriate view and return it DataSourceView newView = ds.GetView(DataMember); if (newView == null) { throw new InvalidOperationException(SR.GetString(SR.DataControl_ViewNotFound, ID)); } _currentViewIsFromDataSourceID = IsBoundUsingDataSourceID; _currentView = newView; if ((_currentView != null) && (_currentViewIsFromDataSourceID)) { // We only care about this event if we are bound through the DataSourceID property _currentView.DataSourceViewChanged += new EventHandler(OnDataSourceViewChanged); } _currentViewValid = true; return _currentView; } protected override ControlCollection CreateControlCollection() { return new EmptyControlCollection(this); } protected void EnsureDataBound() { try { _throwOnDataPropertyChange = true; if (RequiresDataBinding && DataSourceID.Length > 0) { DataBind(); } } finally{ _throwOnDataPropertyChange = false; } } ////// Returns an IEnumerable that is the DataSource, which either came /// from the DataSource property or from the control bound via the /// DataSourceID property. /// protected virtual IEnumerable GetData() { DataSourceView view = ConnectToDataSourceView(); Debug.Assert(_currentViewValid); if (view != null) { return view.ExecuteSelect(DataSourceSelectArguments.Empty); } return null; } /* * Override to load items and selected indices. */ ////// /// protected override void LoadViewState(object savedState) { if (savedState != null) { Triplet statetriplet = (Triplet)savedState; base.LoadViewState(statetriplet.First); // restore state of items ((IStateManager)Items).LoadViewState(statetriplet.Second); // restore selected indices object selectedIndices = statetriplet.Third; if (selectedIndices != null) Select((int[])selectedIndices); } } ////// /// protected override void OnDataBinding(EventArgs e) { base.OnDataBinding(e); // create items using the datasource IEnumerable dataSource = GetData(); // create items using the datasource if (dataSource != null) { bool fieldsSpecified = false; string textField = DataTextField; string valueField = DataValueField; Items.Clear(); ICollection collection = dataSource as ICollection; if (collection != null) { Items.Capacity = collection.Count; } if ((textField.Length != 0) || (valueField.Length != 0)) fieldsSpecified = true; foreach (object dataItem in dataSource) { ListItem item = new ListItem(); if (fieldsSpecified) { if (textField.Length > 0) { item.Text = DataBinder.GetPropertyValue(dataItem,textField,null); } if (valueField.Length > 0) { item.Value = DataBinder.GetPropertyValue(dataItem,valueField,null); } } else { item.Text = item.Value = dataItem.ToString(); } Items.Add(item); } } // try to apply the cached SelectedIndex now if (cachedSelectedIndex != -1) { SelectedIndex = cachedSelectedIndex; cachedSelectedIndex = -1; } ViewState[DataBoundViewStateKey] = true; RequiresDataBinding = false; } ////// This method is called when DataMember, DataSource, or DataSourceID is changed. /// protected virtual void OnDataPropertyChanged() { if (_throwOnDataPropertyChange) { throw new HttpException(SR.GetString(SR.DataBoundControl_InvalidDataPropertyChange, ID)); } if (_inited) { RequiresDataBinding = true; } _currentViewValid = false; } protected virtual void OnDataSourceViewChanged(object sender, EventArgs e) { RequiresDataBinding = true; } protected internal override void OnInit(EventArgs e) { base.OnInit(e); if (Page != null) { Page.PreLoad += new EventHandler(this.OnPagePreLoad); if (!IsViewStateEnabled && Page.IsPostBack) { RequiresDataBinding = true; } } } protected internal override void OnLoad(EventArgs e) { _inited = true; // just in case we were added to the page after PreLoad ConnectToDataSourceView(); if (Page != null && !_pagePreLoadFired && ViewState[DataBoundViewStateKey] == null) { // If the control was added after PagePreLoad, we still need to databind it because it missed its // first change in PagePreLoad. If this control was created by a call to a parent control's DataBind // in Page_Load (with is relatively common), this control will already have been databound even // though pagePreLoad never fired and the page isn't a postback. if (!Page.IsPostBack) { RequiresDataBinding = true; } // If the control was added to the page after page.PreLoad, we'll never get the event and we'll // never databind the control. So if we're catching up and Load happens but PreLoad never happened, // call DataBind. This may make the control get databound twice if the user called DataBind on the control // directly in Page.OnLoad, but better to bind twice than never to bind at all. else if (IsViewStateEnabled) { RequiresDataBinding = true; } } base.OnLoad(e); } private void OnPagePreLoad(object sender, EventArgs e) { _inited = true; if (Page != null) { Page.PreLoad -= new EventHandler(this.OnPagePreLoad); // Setting RequiresDataBinding to true in OnLoad is too late because the OnLoad page event // happens before the control.OnLoad method gets called. So a page_load handler on the page // that calls DataBind won't prevent DataBind from getting called again in PreRender. if (!Page.IsPostBack) { RequiresDataBinding = true; } // If this is a postback and viewstate is enabled, but we have never bound the control // before, it is probably because its visibility was changed in the postback. In this // case, we need to bind the control or it will never appear. This is a common scenario // for Wizard and MultiView. if (Page.IsPostBack && IsViewStateEnabled && ViewState[DataBoundViewStateKey] == null) { RequiresDataBinding = true; } } _pagePreLoadFired = true; } /* * This method is invoked just prior to rendering. */ ////// /// protected internal override void OnPreRender(EventArgs e) { base.OnPreRender(e); // An Html SELECT does not post when nothing is selected. if (Page != null && !Disabled) { if (Size > 1) { Page.RegisterRequiresPostBack(this); } Page.RegisterEnabledControl(this); } EnsureDataBound(); } /* * Method used to raise the OnServerChange event. */ ////// protected virtual void OnServerChange(EventArgs e) { EventHandler handler = (EventHandler)Events[EventServerChange]; if (handler != null) handler(this, e); } /* * Override to prevent SelectedIndex from being rendered as an attribute. */ ////// Raised /// on the server when the ///control list values /// change between postback requests. /// /// /// protected override void RenderAttributes(HtmlTextWriter writer) { if (Page != null) { Page.ClientScript.RegisterForEventValidation(RenderedNameAttribute); } writer.WriteAttribute("name", RenderedNameAttribute); Attributes.Remove("name"); Attributes.Remove("DataValueField"); Attributes.Remove("DataTextField"); Attributes.Remove("DataMember"); Attributes.Remove("DataSourceID"); base.RenderAttributes(writer); } /* * Render the Items in the list. */ ////// /// protected internal override void RenderChildren(HtmlTextWriter writer) { bool selected = false; bool isSingle = !Multiple; writer.WriteLine(); writer.Indent++; ListItemCollection liCollection = Items; int n = liCollection.Count; if (n > 0) { for (int i=0; i < n; i++) { ListItem li = liCollection[i]; writer.WriteBeginTag("option"); if (li.Selected) { if (isSingle) { if (selected) throw new HttpException(SR.GetString(SR.HtmlSelect_Cant_Multiselect_In_Single_Mode)); selected=true; } writer.WriteAttribute("selected", "selected"); } writer.WriteAttribute("value", li.Value, true /*fEncode*/); // This is to fix the case where the user puts one of these // three values in the AttributeCollection. Removing them // at least is better than rendering them twice. li.Attributes.Remove("text"); li.Attributes.Remove("value"); li.Attributes.Remove("selected"); li.Attributes.Render(writer); writer.Write(HtmlTextWriter.TagRightChar); HttpUtility.HtmlEncode(li.Text, writer); writer.WriteEndTag("option"); writer.WriteLine(); } } writer.Indent--; } /* * Save selected indices and modified Items. */ ////// /// protected override object SaveViewState() { object baseState = base.SaveViewState(); object items = ((IStateManager)Items).SaveViewState(); object selectedindices = null; // only save selection if handler is registered, // we are disabled, or we are not visible // since selection is always posted back otherwise if (Events[EventServerChange] != null || Disabled || !Visible) selectedindices = SelectedIndices; if (selectedindices != null || items != null || baseState != null) return new Triplet(baseState, items, selectedindices); return null; } ////// /// protected virtual void Select(int[] selectedIndices) { ClearSelection(); for (int i=0; i < selectedIndices.Length; i++) { int n = selectedIndices[i]; if (n >= 0 && n < Items.Count) Items[n].Selected = true; } } /* * TrackState */ ////// /// protected override void TrackViewState() { base.TrackViewState(); ((IStateManager)Items).TrackViewState(); } /* * Method of IPostBackDataHandler interface to process posted data. * SelectList processes a newly posted value. */ ////// /// bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { return LoadPostData(postDataKey, postCollection); } ////// /// protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) { string[] selectedItems = postCollection.GetValues(postDataKey); bool selectionChanged = false; if (selectedItems != null) { if (!Multiple) { int n = Items.FindByValueInternal(selectedItems[0], false); if (SelectedIndex != n) { SelectedIndex = n; selectionChanged = true; } } else { // multiple selection int count = selectedItems.Length; int[] oldSelectedIndices = SelectedIndices; int[] newSelectedIndices = new int[count]; for (int i=0; i < count; i++) { // create array of new indices from posted values newSelectedIndices[i] = Items.FindByValueInternal(selectedItems[i], false); } if (oldSelectedIndices.Length == count) { // check new indices against old indices // assumes selected values are posted in order for (int i=0; i < count; i++) { if (newSelectedIndices[i] != oldSelectedIndices[i]) { selectionChanged = true; break; } } } else { // indices must have changed if count is different selectionChanged = true; } if (selectionChanged) { // select new indices Select(newSelectedIndices); } } } else { // no items selected if (SelectedIndex != -1) { SelectedIndex = -1; selectionChanged = true; } } if (selectionChanged) { ValidateEvent(postDataKey); } return selectionChanged; } /* * Method of IPostBackDataHandler interface which is invoked whenever posted data * for a control has changed. SelectList fires an OnServerChange event. */ ////// /// void IPostBackDataHandler.RaisePostDataChangedEvent() { RaisePostDataChangedEvent(); } ////// /// protected virtual void RaisePostDataChangedEvent() { OnServerChange(EventArgs.Empty); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- VirtualPathProvider.cs
- TdsParserSessionPool.cs
- HighContrastHelper.cs
- RequestTimeoutManager.cs
- HyperLinkColumn.cs
- DataRelationPropertyDescriptor.cs
- RootAction.cs
- SqlNamer.cs
- Debug.cs
- AnnouncementSendsAsyncResult.cs
- AttachedPropertyBrowsableWhenAttributePresentAttribute.cs
- RegexStringValidatorAttribute.cs
- MultipleViewPatternIdentifiers.cs
- XmlDeclaration.cs
- XmlNodeList.cs
- safemediahandle.cs
- RTLAwareMessageBox.cs
- TreeViewCancelEvent.cs
- DecryptRequest.cs
- ReferenceList.cs
- PenThread.cs
- DataPagerFieldItem.cs
- Calendar.cs
- AsymmetricSignatureDeformatter.cs
- RotateTransform.cs
- StateMachine.cs
- AssociationSetMetadata.cs
- HtmlEmptyTagControlBuilder.cs
- SubstitutionResponseElement.cs
- WsatAdminException.cs
- ProtocolsConfiguration.cs
- SslStream.cs
- EntityDataSourceDesigner.cs
- GenericPrincipal.cs
- Span.cs
- SoapProtocolImporter.cs
- JsonDeserializer.cs
- ButtonPopupAdapter.cs
- LogReserveAndAppendState.cs
- CodeAttributeArgumentCollection.cs
- ChangeTracker.cs
- NonSerializedAttribute.cs
- SqlClientWrapperSmiStream.cs
- MachineKeyConverter.cs
- ValueTypeFieldReference.cs
- AspNetSynchronizationContext.cs
- ClientSponsor.cs
- BrushConverter.cs
- CodeMethodInvokeExpression.cs
- OleDbConnectionFactory.cs
- X509ServiceCertificateAuthentication.cs
- ValidatorCompatibilityHelper.cs
- ChangeDirector.cs
- TextContainerHelper.cs
- DockEditor.cs
- SessionViewState.cs
- XamlSerializationHelper.cs
- XmlReaderSettings.cs
- StringArrayConverter.cs
- WsatAdminException.cs
- ResourceProviderFactory.cs
- DateTimeOffsetConverter.cs
- TreeView.cs
- MediaContext.cs
- ProfilePropertyMetadata.cs
- DetailsViewUpdateEventArgs.cs
- XmlWrappingReader.cs
- ViewStateModeByIdAttribute.cs
- BinaryFormatterWriter.cs
- EmptyControlCollection.cs
- Preprocessor.cs
- TextEmbeddedObject.cs
- HMACMD5.cs
- TaiwanCalendar.cs
- SpellerHighlightLayer.cs
- ImageBrush.cs
- Stackframe.cs
- ServiceObjectContainer.cs
- XmlElementList.cs
- HttpCacheVary.cs
- CodeAccessSecurityEngine.cs
- WebContext.cs
- DragStartedEventArgs.cs
- EventlogProvider.cs
- WsrmFault.cs
- ColorConvertedBitmapExtension.cs
- DataGridViewSelectedCellCollection.cs
- Selector.cs
- ClrPerspective.cs
- TargetControlTypeAttribute.cs
- CollectionChangedEventManager.cs
- Utils.cs
- BaseValidatorDesigner.cs
- HttpModuleCollection.cs
- GetIndexBinder.cs
- DrawingAttributes.cs
- Util.cs
- TextParagraphProperties.cs
- Renderer.cs
- WindowsTreeView.cs