2 // System.Web.UI.WebControls.ListControl.cs
5 // Jackson Harper (jackson@ximian.com)
7 // (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.
31 using System.Web.Util;
32 using System.Collections;
33 using System.Globalization;
34 using System.ComponentModel;
35 using System.Collections.Specialized;
37 namespace System.Web.UI.WebControls {
39 [DataBindingHandler("System.Web.UI.Design.WebControls.ListControlDataBindingHandler, " + Consts.AssemblySystem_Design)]
40 [DefaultEventAttribute ("SelectedIndexChanged")]
42 [DefaultPropertyAttribute ("DataSource")]
44 [Designer("System.Web.UI.Design.WebControls.ListControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
46 [ControlValueProperty ("SelectedValue", null)]
47 [ParseChildrenAttribute (true, "Items", ChildControlType = typeof (Control))]
49 [ParseChildrenAttribute (true, "Items")]
51 public abstract class ListControl :
53 DataBoundControl, IEditableTextControl, ITextControl
59 private static readonly object SelectedIndexChangedEvent = new object ();
61 private static readonly object TextChangedEvent = new object ();
64 private ListItemCollection items;
65 int saved_selected_index = -2;
66 string saved_selected_value;
68 public ListControl () : base (HtmlTextWriterTag.Select)
73 [DefaultValue (false)]
76 [WebSysDescription ("")]
77 [WebCategory ("Behavior")]
78 public virtual bool AppendDataBoundItems
81 return ViewState.GetBool ("AppendDataBoundItems", false);
84 ViewState ["AppendDataBoundItems"] = value;
93 [WebSysDescription ("")]
94 [WebCategory ("Behavior")]
95 public virtual bool AutoPostBack {
96 get { return ViewState.GetBool ("AutoPostBack", false); }
97 set { ViewState ["AutoPostBack"] = value; }
102 [WebSysDescription ("")]
103 [WebCategory ("Data")]
104 public virtual string DataMember {
105 get { return ViewState.GetString ("DataMember", String.Empty); }
106 set { ViewState ["DataMember"] = value; }
109 private object data_source;
113 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
114 [WebSysDescription ("")]
115 [WebCategory ("Data")]
116 public virtual object DataSource {
117 get { return data_source; }
119 if(value == null || value is IListSource || value is IEnumerable) {
123 throw new ArgumentException("Invalid DataSource Type");
132 [WebSysDescription ("")]
133 [WebCategory ("Data")]
134 public virtual string DataTextField {
135 get { return ViewState.GetString ("DataTextField", String.Empty); }
136 set { ViewState ["DataTextField"] = value; }
143 [WebSysDescription ("")]
144 [WebCategory ("Data")]
145 public virtual string DataTextFormatString {
146 get { return ViewState.GetString ("DataTextFormatString", String.Empty); }
147 set { ViewState ["DataTextFormatString"] = value; }
154 [WebSysDescription ("")]
155 [WebCategory ("Data")]
156 public virtual string DataValueField {
157 get { return ViewState.GetString ("DataValueField", String.Empty); }
158 set { ViewState ["DataValueField"] = value; }
162 [Editor ("System.Web.UI.Design.WebControls.ListItemsCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
165 [MergableProperty(false)]
166 [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
167 [WebSysDescription ("")]
168 [WebCategory ("Misc")]
169 public virtual ListItemCollection Items {
172 items = new ListItemCollection ();
177 // I can't find this info stored in the viewstate anywhere
178 // so it must be calculated on the fly.
182 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
186 [WebSysDescription ("")]
187 [WebCategory ("Misc")]
188 public virtual int SelectedIndex {
192 for (int i = 0; i < items.Count; i++) {
193 if (items [i].Selected)
199 if (items == null || items.Count == 0) {
200 // This will happen when assigning this property
201 // before DataBind () is called on the control.
202 saved_selected_index = value;
206 if (value < -1 || value >= Items.Count)
207 throw new ArgumentOutOfRangeException ("value");
213 items [value].Selected = true;
215 /* you'd think this would be called, but noooo */
216 //OnSelectedIndexChanged (EventArgs.Empty);
222 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
223 [WebSysDescription ("")]
224 [WebCategory ("Misc")]
225 public virtual ListItem SelectedItem {
227 int si = SelectedIndex;
235 [Bindable(true, BindingDirection.TwoWay)]
242 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
243 [WebSysDescription ("")]
244 [WebCategory ("Misc")]
245 public virtual string SelectedValue {
247 int si = SelectedIndex;
250 return Items [si].Value;
254 if (items == null || items.Count == 0) {
255 // This will happen when assigning this property
256 // before DataBind () is called on the control.
257 saved_selected_value = value;
261 int count = Items.Count;
262 ListItemCollection coll = Items;
264 for (int i = 0; i < count; i++) {
265 if (coll [i].Value == value) {
266 coll [i].Selected = true;
272 string msg = String.Format ("Argument value is out of range: {0}", value);
273 throw new ArgumentOutOfRangeException (msg);
281 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
284 [WebSysDescription ("")]
285 [WebCategoryAttribute ("Behavior")]
286 public virtual string Text {
288 return SelectedValue;
291 SelectedValue = value;
292 /* you'd think this would be called, but noooo */
293 //OnTextChanged (EventArgs.Empty);
297 #if HAVE_CONTROL_ADAPTERS
298 protected virtual new
302 HtmlTextWriterTag TagKey
305 return HtmlTextWriterTag.Select;
309 protected override void AddAttributesToRender (HtmlTextWriter w)
311 base.AddAttributesToRender (w);
316 public virtual void ClearSelection ()
321 int count = Items.Count;
322 for (int i = 0; i<count; i++)
323 items [i].Selected = false;
327 protected internal override void LoadControlState (object savedState)
330 ArrayList indices = null;
331 Pair pair = savedState as Pair;
335 indices = pair.Second as ArrayList;
338 base.LoadControlState (first);
340 if (indices != null) {
341 int count = Items.Count;
342 foreach (int index in indices) {
343 if (index >= 0 && index < count)
344 Items [index].Selected = true;
350 protected override void OnDataBinding (EventArgs e)
352 base.OnDataBinding (e);
354 IEnumerable list = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
359 if (!AppendDataBoundItems)
364 DoDataBinding (list);
366 if (saved_selected_value != null) {
367 SelectedValue = saved_selected_value;
368 if (saved_selected_index != -2 && saved_selected_index != SelectedIndex)
369 throw new ArgumentException ("SelectedIndex and SelectedValue are mutually exclusive.");
370 } else if (saved_selected_index != -2) {
371 SelectedIndex = saved_selected_index;
372 // No need to check saved_selected_value here, as it's done before.
377 protected internal override void OnInit (EventArgs e)
379 Page.RegisterRequiresControlState (this);
389 override void OnPreRender (EventArgs e)
391 base.OnPreRender (e);
394 void DoDataBinding (IEnumerable dataSource)
396 if (dataSource != null) {
397 string format = DataTextFormatString;
401 string text_field = DataTextField;
402 string value_field = DataValueField;
403 ListItemCollection coll = Items;
404 foreach (object container in dataSource) {
409 if (text_field != "") {
410 text = DataBinder.GetPropertyValue (container, text_field, format);
413 if (value_field != "") {
414 val = DataBinder.GetPropertyValue (container, value_field).ToString ();
415 } else if (text_field == "") {
416 text = val = container.ToString ();
418 text = String.Format (format, container);
419 } else if (text != null) {
426 coll.Add (new ListItem (text, val));
432 protected virtual void OnTextChanged (EventArgs e)
434 EventHandler handler = (EventHandler) Events [TextChangedEvent];
439 protected internal override void PerformDataBinding (IEnumerable dataSource)
441 base.PerformDataBinding (dataSource);
443 DoDataBinding (dataSource);
446 [MonoTODO ("why override?")]
447 protected override void PerformSelect ()
449 base.PerformSelect ();
453 protected internal override void RenderContents (HtmlTextWriter w)
455 base.RenderContents (w);
458 protected internal override object SaveControlState ()
463 first = base.SaveControlState ();
464 second = GetSelectedIndicesInternal ();
466 second = new ArrayList();
468 return new Pair (first, second);
472 internal ArrayList GetSelectedIndicesInternal ()
474 ArrayList selected = null;
476 selected = new ArrayList ();
477 int count = Items.Count;
478 for (int i = 0; i < count; i++) {
479 if (items [i].Selected)
486 protected override object SaveViewState ()
489 object second = null;
491 first = base.SaveViewState ();
493 IStateManager manager = items as IStateManager;
495 second = manager.SaveViewState ();
498 ArrayList selected = GetSelectedIndicesInternal ();
501 if (first == null && second == null
509 return new Pair (first, second);
511 return new Triplet (first, second, selected);
515 protected override void LoadViewState (object savedState)
518 object second = null;
520 ArrayList indices = null;
524 Pair pair = savedState as Pair;
527 second = pair.Second;
530 Triplet triplet = savedState as Triplet;
531 if (triplet != null) {
532 first = triplet.First;
533 second = triplet.Second;
534 indices = triplet.Third as ArrayList;
538 base.LoadViewState (first);
540 if (second != null) {
541 IStateManager manager = Items as IStateManager;
542 manager.LoadViewState (second);
546 if (indices != null) {
547 foreach (int index in indices)
548 Items [index].Selected = true;
555 protected void SetPostDataSelection (int selectedIndex)
557 throw new NotImplementedException ();
561 protected override void TrackViewState ()
563 base.TrackViewState ();
564 IStateManager manager = items as IStateManager;
566 manager.TrackViewState ();
569 protected virtual void OnSelectedIndexChanged (EventArgs e)
571 EventHandler handler = (EventHandler) Events [SelectedIndexChangedEvent];
577 protected internal virtual void VerifyMultiSelect ()
582 [WebSysDescription ("")]
583 [WebCategory ("Action")]
584 public event EventHandler SelectedIndexChanged {
585 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
586 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
590 /* sealed in the docs */
591 public event EventHandler TextChanged {
593 Events.AddHandler (TextChangedEvent, value);
596 Events.RemoveHandler (TextChangedEvent, value);
603 [DefaultValue (false)]
604 [WebSysDescription ("")]
605 [WebCategory ("Behavior")]
606 public virtual bool CausesValidation {
608 throw new NotImplementedException ();
611 throw new NotImplementedException ();
618 [WebSysDescription ("")]
619 [WebCategoryAttribute ("Behavior")]
620 public virtual string ValidationGroup {
622 throw new NotImplementedException ();
625 throw new NotImplementedException ();