// // System.Web.UI.HtmlControls.HtmlSelect.cs // // Author: // Dick Porter // // Copyright (C) 2005 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Web.UI; using System.Web.UI.WebControls; using System.Web.Util; using System.ComponentModel; using System.Collections; using System.Collections.Specialized; using System.Globalization; namespace System.Web.UI.HtmlControls { [DefaultEvent ("ServerChange")] [ValidationProperty ("Value")] [ControlBuilder (typeof (HtmlSelectBuilder))] public class HtmlSelect : HtmlContainerControl , IPostBackDataHandler #if NET_2_0 , IParserAccessor #endif { public HtmlSelect () : base ("select") { } [DefaultValue ("")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public virtual string DataMember { get { string member = Attributes["datamember"]; if (member == null) { return (String.Empty); } return (member); } set { if (value == null) { Attributes.Remove ("datamember"); } else { Attributes["datamember"] = value; } } } object datasource; [DefaultValue (null)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public virtual object DataSource { get { return (datasource); } set { if ((value != null) && !(value is IEnumerable) && !(value is IListSource)) { throw new ArgumentException (); } datasource = value; } } #if NET_2_0 [DefaultValue ("")] public virtual string DataSourceID { get { return (String.Empty); } set { } } #endif [DefaultValue ("")] public virtual string DataTextField { get { string text = Attributes["datatextfield"]; if (text == null) { return (String.Empty); } return (text); } set { if (value == null) { Attributes.Remove ("datatextfield"); } else { Attributes["datatextfield"] = value; } } } [DefaultValue ("")] public virtual string DataValueField { get { string value = Attributes["datavaluefield"]; if (value == null) { return (String.Empty); } return (value); } set { if (value == null) { Attributes.Remove ("datavaluefield"); } else { Attributes["datavaluefield"] = value; } } } public override string InnerHtml { get { throw new NotSupportedException (); } set { throw new NotSupportedException (); } } public override string InnerText { get { throw new NotSupportedException (); } set { throw new NotSupportedException (); } } #if NET_2_0 [MonoTODO] protected bool IsBoundUsingDataSourceID { get { throw new NotImplementedException (); } } #endif ListItemCollection items; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public ListItemCollection Items { get { if (items == null) { items = new ListItemCollection (); } return (items); } } [DefaultValue ("")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool Multiple { get { string multi = Attributes["multiple"]; if (multi == null) { return (false); } return (true); } set { if (value == false) { Attributes.Remove ("multiple"); } else { Attributes["multiple"] = "multiple"; } } } [DefaultValue ("")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public string Name { get { return (UniqueID); } set { /* Do nothing */ } } #if NET_2_0 [MonoTODO] protected bool RequiresDataBinding { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } #endif [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public virtual int SelectedIndex { get { /* Make sure Items has been initialised */ ListItemCollection listitems = Items; for (int i = 0; i < listitems.Count; i++) { if (listitems[i].Selected) { return (i); } } /* There is always a selected item in * non-multiple mode, if the size is * <= 1 */ if (!Multiple && Size <= 1) { /* Select the first item */ if (listitems.Count > 0) { /* And make it stick * if there is * anything in the * list */ listitems[0].Selected = true; } return (0); } return (-1); } set { ClearSelection (); if (value == -1 || items == null) { return; } if (value < 0 || value >= items.Count) { throw new ArgumentOutOfRangeException ("value"); } items[value].Selected = true; } } /* "internal infrastructure" according to the docs, * but has some documentation in 2.0 */ protected virtual int[] SelectedIndices { get { ArrayList selected = new ArrayList (); int count = Items.Count; for (int i = 0; i < count; i++) { if (Items [i].Selected) { selected.Add (i); } } return ((int[])selected.ToArray (typeof (int))); } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public int Size { get { string size = Attributes["size"]; if (size == null) { return (-1); } return (Int32.Parse (size, CultureInfo.InvariantCulture)); } set { if (value == -1) { Attributes.Remove ("size"); } else { Attributes["size"] = value.ToString (); } } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public string Value { get { int sel = SelectedIndex; if (sel >= 0 && sel < Items.Count) { return (Items[sel].Value); } return (String.Empty); } set { int sel = Items.IndexOf (value); if (sel >= 0) { SelectedIndex = sel; } } } private static readonly object EventServerChange = new object (); public event EventHandler ServerChange { add { Events.AddHandler (EventServerChange, value); } remove { Events.RemoveHandler (EventServerChange, value); } } protected override void AddParsedSubObject (object obj) { if (!(obj is ListItem)) { throw new HttpException ("HtmlSelect can only contain ListItem"); } Items.Add ((ListItem)obj); base.AddParsedSubObject (obj); } /* "internal infrastructure" according to the docs, * but has some documentation in 2.0 */ protected virtual void ClearSelection () { if (items == null) { return; } int count = items.Count; for (int i = 0; i < count; i++) { items[i].Selected = false; } } protected override ControlCollection CreateControlCollection () { return (base.CreateControlCollection ()); } #if NET_2_0 [MonoTODO] protected void EnsureDataBound () { throw new NotImplementedException (); } [MonoTODO] protected virtual IEnumerable GetData () { throw new NotImplementedException (); } #endif protected override void LoadViewState (object savedState) { object first = null; object second = null; int[] selected = null; Triplet triplet = savedState as Triplet; if (triplet != null) { first = triplet.First; second = triplet.Second; selected = triplet.Third as int[]; } base.LoadViewState (first); if (second != null) { IStateManager manager = Items as IStateManager; manager.LoadViewState (second); } if (selected != null) { Select (selected); } } protected override void OnDataBinding (EventArgs e) { base.OnDataBinding (e); /* Make sure Items has been initialised */ ListItemCollection listitems = Items; listitems.Clear (); IEnumerable list = DataSourceResolver.ResolveDataSource (DataSource, DataMember); if (list == null) { return; } foreach (object container in list) { string text = null; string value = null; if (DataTextField == String.Empty && DataValueField == String.Empty) { text = container.ToString (); value = text; } else { if (DataTextField != String.Empty) { text = DataBinder.Eval (container, DataTextField).ToString (); } if (DataValueField != String.Empty) { value = DataBinder.Eval (container, DataValueField).ToString (); } else { value = text; } if (text == null && value != null) { text = value; } } if (text == null) { text = String.Empty; } if (value == null) { value = String.Empty; } ListItem item = new ListItem (text, value); listitems.Add (item); } } #if NET_2_0 [MonoTODO] protected virtual void OnDataPropertyChanged () { RequiresDataBinding = true; throw new NotImplementedException (); } [MonoTODO] protected virtual void OnDataSourceViewChanged (object sender, EventArgs e) { RequiresDataBinding = true; throw new NotImplementedException (); } [MonoTODO] protected internal override void OnInit (EventArgs e) { /* if (IsViewStateEnabled == false && Page.IsPostBack == true) { RequiresDataBinding = true; } */ throw new NotImplementedException (); } [MonoTODO] protected internal override void OnLoad (EventArgs e) { throw new NotImplementedException (); } #endif #if NET_2_0 protected internal #else protected #endif override void OnPreRender (EventArgs e) { base.OnPreRender (e); if (Page != null) { Page.RegisterRequiresPostBack (this); } } protected virtual void OnServerChange (EventArgs e) { EventHandler handler = (EventHandler)Events[EventServerChange]; if (handler != null) { handler (this, e); } } protected override void RenderAttributes (HtmlTextWriter w) { /* If there is no "name" attribute, * LoadPostData doesn't work... */ w.WriteAttribute ("name", Name); Attributes.Remove ("name"); /* Don't render the databinding attributes */ Attributes.Remove ("datamember"); Attributes.Remove ("datatextfield"); Attributes.Remove ("datavaluefield"); base.RenderAttributes (w); } #if NET_2_0 protected internal #else protected #endif override void RenderChildren (HtmlTextWriter w) { base.RenderChildren (w); if (items == null) { return; } w.WriteLine (); bool done_sel = false; int count = items.Count; for (int i = 0; i < count; i++) { ListItem item = items[i]; w.Indent++; /* Write the