2 // System.Web.UI.HtmlControls.HtmlSelect.cs
5 // Dick Porter <dick@ximian.com>
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Web.UI.WebControls;
31 using System.Web.Util;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.Globalization;
37 namespace System.Web.UI.HtmlControls
39 [DefaultEvent ("ServerChange")]
40 [ValidationProperty ("Value")]
41 [ControlBuilder (typeof (HtmlSelectBuilder))]
42 public class HtmlSelect : HtmlContainerControl , IPostBackDataHandler
47 public HtmlSelect () : base ("select")
52 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
53 [WebSysDescription("")]
55 public virtual string DataMember
58 string member = Attributes["datamember"];
61 return (String.Empty);
68 Attributes.Remove ("datamember");
70 Attributes["datamember"] = value;
78 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
79 [WebSysDescription("")]
81 public virtual object DataSource
87 if ((value != null) &&
88 !(value is IEnumerable) &&
89 !(value is IListSource)) {
90 throw new ArgumentException ();
99 public virtual string DataSourceID
102 return (String.Empty);
111 [WebSysDescription("")]
112 [WebCategory("Data")]
113 public virtual string DataTextField
116 string text = Attributes["datatextfield"];
119 return (String.Empty);
126 Attributes.Remove ("datatextfield");
128 Attributes["datatextfield"] = value;
134 [WebSysDescription("")]
135 [WebCategory("Data")]
136 public virtual string DataValueField
139 string value = Attributes["datavaluefield"];
142 return (String.Empty);
149 Attributes.Remove ("datavaluefield");
151 Attributes["datavaluefield"] = value;
156 public override string InnerHtml
159 throw new NotSupportedException ();
162 throw new NotSupportedException ();
166 public override string InnerText
169 throw new NotSupportedException ();
172 throw new NotSupportedException ();
178 protected bool IsBoundUsingDataSourceID
181 throw new NotImplementedException ();
186 ListItemCollection items;
188 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
190 public ListItemCollection Items
194 items = new ListItemCollection ();
202 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
203 [WebSysDescription("")]
204 [WebCategory("Behavior")]
208 string multi = Attributes["multiple"];
217 if (value == false) {
218 Attributes.Remove ("multiple");
220 Attributes["multiple"] = "multiple";
226 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
227 [WebSysDescription("")]
228 [WebCategory("Behavior")]
241 protected bool RequiresDataBinding
244 throw new NotImplementedException ();
247 throw new NotImplementedException ();
252 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
254 public virtual int SelectedIndex
257 /* Make sure Items has been initialised */
258 ListItemCollection listitems = Items;
260 for (int i = 0; i < listitems.Count; i++) {
261 if (listitems[i].Selected) {
266 /* There is always a selected item in
267 * non-multiple mode, if the size is
270 if (!Multiple && Size <= 1) {
271 /* Select the first item */
272 if (listitems.Count > 0) {
278 listitems[0].Selected = true;
289 if (value == -1 || items == null) {
293 if (value < 0 || value >= items.Count) {
294 throw new ArgumentOutOfRangeException ("value");
297 items[value].Selected = true;
301 /* "internal infrastructure" according to the docs,
302 * but has some documentation in 2.0
304 protected virtual int[] SelectedIndices
307 ArrayList selected = new ArrayList ();
309 int count = Items.Count;
311 for (int i = 0; i < count; i++) {
312 if (Items [i].Selected) {
317 return ((int[])selected.ToArray (typeof (int)));
322 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
326 string size = Attributes["size"];
332 return (Int32.Parse (size, CultureInfo.InvariantCulture));
336 Attributes.Remove ("size");
338 Attributes["size"] = value.ToString ();
343 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
347 int sel = SelectedIndex;
349 if (sel >= 0 && sel < Items.Count) {
350 return (Items[sel].Value);
353 return (String.Empty);
356 int sel = Items.IndexOf (value);
364 private static readonly object EventServerChange = new object ();
366 [WebSysDescription("")]
367 [WebCategory("Action")]
368 public event EventHandler ServerChange
371 Events.AddHandler (EventServerChange, value);
374 Events.RemoveHandler (EventServerChange, value);
378 protected override void AddParsedSubObject (object obj)
380 if (!(obj is ListItem)) {
381 throw new HttpException ("HtmlSelect can only contain ListItem");
384 Items.Add ((ListItem)obj);
386 base.AddParsedSubObject (obj);
389 /* "internal infrastructure" according to the docs,
390 * but has some documentation in 2.0
392 protected virtual void ClearSelection ()
398 int count = items.Count;
399 for (int i = 0; i < count; i++) {
400 items[i].Selected = false;
404 protected override ControlCollection CreateControlCollection ()
406 return (base.CreateControlCollection ());
411 protected void EnsureDataBound ()
413 throw new NotImplementedException ();
417 protected virtual IEnumerable GetData ()
419 throw new NotImplementedException ();
423 protected override void LoadViewState (object savedState)
426 object second = null;
427 int[] selected = null;
429 Triplet triplet = savedState as Triplet;
430 if (triplet != null) {
431 first = triplet.First;
432 second = triplet.Second;
433 selected = triplet.Third as int[];
436 base.LoadViewState (first);
438 if (second != null) {
439 IStateManager manager = Items as IStateManager;
440 manager.LoadViewState (second);
443 if (selected != null) {
448 protected override void OnDataBinding (EventArgs e)
450 base.OnDataBinding (e);
452 /* Make sure Items has been initialised */
453 ListItemCollection listitems = Items;
457 IEnumerable list = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
463 foreach (object container in list) {
467 if (DataTextField == String.Empty &&
468 DataValueField == String.Empty) {
469 text = container.ToString ();
472 if (DataTextField != String.Empty) {
473 text = DataBinder.Eval (container, DataTextField).ToString ();
476 if (DataValueField != String.Empty) {
477 value = DataBinder.Eval (container, DataValueField).ToString ();
492 value = String.Empty;
495 ListItem item = new ListItem (text, value);
496 listitems.Add (item);
502 protected virtual void OnDataPropertyChanged ()
504 RequiresDataBinding = true;
505 throw new NotImplementedException ();
509 protected virtual void OnDataSourceViewChanged (object sender,
512 RequiresDataBinding = true;
513 throw new NotImplementedException ();
517 protected internal override void OnInit (EventArgs e)
520 if (IsViewStateEnabled == false &&
521 Page.IsPostBack == true) {
522 RequiresDataBinding = true;
525 throw new NotImplementedException ();
529 protected internal override void OnLoad (EventArgs e)
531 throw new NotImplementedException ();
540 override void OnPreRender (EventArgs e)
542 base.OnPreRender (e);
545 Page.RegisterRequiresPostBack (this);
549 protected virtual void OnServerChange (EventArgs e)
551 EventHandler handler = (EventHandler)Events[EventServerChange];
553 if (handler != null) {
558 protected override void RenderAttributes (HtmlTextWriter w)
560 /* If there is no "name" attribute,
561 * LoadPostData doesn't work...
563 w.WriteAttribute ("name", Name);
564 Attributes.Remove ("name");
566 /* Don't render the databinding attributes */
567 Attributes.Remove ("datamember");
568 Attributes.Remove ("datatextfield");
569 Attributes.Remove ("datavaluefield");
571 base.RenderAttributes (w);
579 override void RenderChildren (HtmlTextWriter w)
581 base.RenderChildren (w);
589 bool done_sel = false;
591 int count = items.Count;
592 for (int i = 0; i < count; i++) {
593 ListItem item = items[i];
597 /* Write the <option> elements this
598 * way so that the output HTML matches
599 * the ms version (can't make
600 * HtmlTextWriterTag.Option an inline
601 * element, cos that breaks other
604 w.WriteBeginTag ("option");
605 if (item.Selected && !done_sel) {
607 w.WriteAttribute ("selected", "selected");
614 w.WriteAttribute ("value", item.Value);
615 w.Write (HtmlTextWriter.TagRightChar);
618 w.WriteEndTag ("option");
625 protected override object SaveViewState ()
628 object second = null;
629 object selected = null;
631 first = base.SaveViewState ();
633 IStateManager manager = items as IStateManager;
634 if (manager != null) {
635 second = manager.SaveViewState ();
638 selected = SelectedIndices;
646 return (new Triplet (first, second, selected));
649 /* "internal infrastructure" according to the docs,
650 * but has some documentation in 2.0
652 protected virtual void Select (int[] selectedIndices)
660 int count = items.Count;
661 foreach (int i in selectedIndices) {
662 if (i >= 0 && i < count) {
663 items[i].Selected = true;
668 protected override void TrackViewState ()
670 base.TrackViewState ();
672 IStateManager manager = items as IStateManager;
673 if (manager != null) {
674 manager.TrackViewState ();
679 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
681 return (LoadPostData (postDataKey, postCollection));
684 protected virtual void RaisePostDataChangedEvent ()
686 RaisePostDataChangedEvent ();
690 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
692 /* postCollection contains the values that are
696 string[] values = postCollection.GetValues (postDataKey);
697 bool changed = false;
699 if (values != null) {
702 * selections. We can't just
703 * set the new list, because
704 * we need to know if the set
705 * has changed from last time
707 int value_len = values.Length;
708 int[] old_sel = SelectedIndices;
709 int[] new_sel = new int[value_len];
710 int old_sel_len = old_sel.Length;
712 for (int i = 0; i < value_len; i++) {
713 new_sel[i] = Items.IndexOf (values[i]);
714 if (old_sel_len != value_len ||
715 old_sel[i] != new_sel[i]) {
724 /* Just take the first one */
725 int sel = Items.IndexOf (values[0]);
727 if (sel != SelectedIndex) {
737 void IPostBackDataHandler.RaisePostDataChangedEvent ()
739 OnServerChange (EventArgs.Empty);