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")]
41 [Designer("System.Web.UI.Design.WebControls.ListControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
42 [ParseChildrenAttribute (true, "Items")]
43 [ControlValueProperty ("SelectedValue", null)]
44 public abstract class ListControl : DataBoundControl, IEditableTextControl, ITextControl
47 static readonly object SelectedIndexChangedEvent = new object ();
48 static readonly object TextChangedEvent = new object ();
50 ListItemCollection items;
51 int _selectedIndex = -2;
52 string _selectedValue;
54 public ListControl () : base (HtmlTextWriterTag.Select)
58 [DefaultValue (false)]
60 [WebSysDescription ("")]
61 [WebCategory ("Behavior")]
62 public virtual bool AppendDataBoundItems
65 return ViewState.GetBool ("AppendDataBoundItems", false);
68 ViewState ["AppendDataBoundItems"] = value;
70 RequiresDataBinding = true;
76 [WebSysDescription ("")]
77 [WebCategory ("Behavior")]
78 public virtual bool AutoPostBack {
79 get { return ViewState.GetBool ("AutoPostBack", false); }
80 set { ViewState ["AutoPostBack"] = value; }
85 [WebSysDescription ("")]
86 [WebCategory ("Data")]
87 public virtual string DataTextField {
88 get { return ViewState.GetString ("DataTextField", String.Empty); }
90 ViewState ["DataTextField"] = value;
92 RequiresDataBinding = true;
98 [WebSysDescription ("")]
99 [WebCategory ("Data")]
100 public virtual string DataTextFormatString {
101 get { return ViewState.GetString ("DataTextFormatString", String.Empty); }
103 ViewState ["DataTextFormatString"] = value;
105 RequiresDataBinding = true;
111 [WebSysDescription ("")]
112 [WebCategory ("Data")]
113 public virtual string DataValueField {
114 get { return ViewState.GetString ("DataValueField", String.Empty); }
116 ViewState ["DataValueField"] = value;
118 RequiresDataBinding = true;
122 [Editor ("System.Web.UI.Design.WebControls.ListItemsCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
124 [MergableProperty(false)]
125 [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
126 [WebSysDescription ("")]
127 [WebCategory ("Misc")]
128 public virtual ListItemCollection Items {
131 items = new ListItemCollection ();
132 if (IsTrackingViewState)
133 ((IStateManager) items).TrackViewState ();
139 // I can't find this info stored in the viewstate anywhere
140 // so it must be calculated on the fly.
144 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
146 [WebSysDescription ("")]
147 [WebCategory ("Misc")]
148 public virtual int SelectedIndex {
152 for (int i = 0; i < items.Count; i++) {
153 if (items [i].Selected)
159 _selectedIndex = value;
162 throw new ArgumentOutOfRangeException ("value");
164 if (value >= Items.Count)
171 items [value].Selected = true;
173 /* you'd think this would be called, but noooo */
174 //OnSelectedIndexChanged (EventArgs.Empty);
180 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
181 [WebSysDescription ("")]
182 [WebCategory ("Misc")]
183 public virtual ListItem SelectedItem {
185 int si = SelectedIndex;
192 [Bindable(true, BindingDirection.TwoWay)]
196 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
197 [WebSysDescription ("")]
198 [WebCategory ("Misc")]
199 public virtual string SelectedValue {
201 int si = SelectedIndex;
204 return Items [si].Value;
207 _selectedValue = value;
208 SetSelectedValue (value);
212 bool SetSelectedValue (string value)
214 if (items != null && items.Count > 0) {
215 int count = items.Count;
216 ListItemCollection coll = Items;
217 for (int i = 0; i < count; i++) {
218 if (coll [i].Value == value) {
220 coll [i].Selected = true;
230 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
232 [WebSysDescription ("")]
233 [WebCategoryAttribute ("Behavior")]
234 public virtual string Text {
236 return SelectedValue;
239 SelectedValue = value;
240 /* you'd think this would be called, but noooo */
241 //OnTextChanged (EventArgs.Empty);
245 #if HAVE_CONTROL_ADAPTERS
246 protected virtual new
250 HtmlTextWriterTag TagKey
253 return HtmlTextWriterTag.Select;
257 protected override void AddAttributesToRender (HtmlTextWriter writer)
259 base.AddAttributesToRender (writer);
262 public virtual void ClearSelection ()
267 int count = Items.Count;
268 for (int i = 0; i<count; i++)
269 items [i].Selected = false;
272 protected override void OnDataBinding (EventArgs e)
274 base.OnDataBinding (e);
275 IEnumerable list = GetData ().ExecuteSelect (DataSourceSelectArguments.Empty);
276 InternalPerformDataBinding (list);
279 protected internal override void OnPreRender (EventArgs e)
281 base.OnPreRender (e);
283 if (page != null && IsEnabled)
284 page.RegisterEnabledControl (this);
287 protected virtual void OnTextChanged (EventArgs e)
289 EventHandler handler = (EventHandler) Events [TextChangedEvent];
294 protected internal override void PerformDataBinding (IEnumerable dataSource)
296 if (dataSource == null)
298 if (!AppendDataBoundItems)
301 string format = DataTextFormatString;
302 if (format.Length == 0)
305 string text_field = DataTextField;
306 string value_field = DataValueField;
308 if (text_field.Length == 0)
310 if (value_field.Length == 0)
313 ListItemCollection coll = Items;
314 foreach (object container in dataSource) {
319 if (text_field != null)
320 text = DataBinder.GetPropertyValue (container, text_field, format);
322 if (value_field != null)
323 val = DataBinder.GetPropertyValue (container, value_field).ToString ();
324 else if (text_field == null) {
325 text = val = container.ToString ();
327 text = String.Format (format, container);
328 } else if (text != null)
334 coll.Add (new ListItem (text, val));
338 if (!String.IsNullOrEmpty (_selectedValue)) {
339 if (!SetSelectedValue (_selectedValue))
340 throw new ArgumentOutOfRangeException ("value", String.Format ("'{0}' has a SelectedValue which is invalid because it does not exist in the list of items.", ID));
341 if (_selectedIndex >= 0 && _selectedIndex != SelectedIndex)
342 throw new ArgumentException ("SelectedIndex and SelectedValue are mutually exclusive.");
344 else if (_selectedIndex >= 0) {
345 SelectedIndex = _selectedIndex;
349 [MonoTODO ("why override?")]
350 protected override void PerformSelect ()
352 OnDataBinding (EventArgs.Empty);
353 RequiresDataBinding = false;
355 OnDataBound (EventArgs.Empty);
358 protected internal override void RenderContents (HtmlTextWriter writer)
360 bool selected = false;
362 for (int i = 0; i < Items.Count; i++) {
363 ListItem item = Items [i];
365 page.ClientScript.RegisterForEventValidation (UniqueID, item.Value);
366 writer.WriteBeginTag ("option");
369 VerifyMultiSelect ();
370 writer.WriteAttribute ("selected", "selected", false);
373 writer.WriteAttribute ("value", item.Value, true);
375 if (item.HasAttributes)
376 item.Attributes.Render (writer);
379 string encoded = HttpUtility.HtmlEncode (item.Text);
380 writer.Write (encoded);
381 writer.WriteEndTag ("option");
386 internal ArrayList GetSelectedIndicesInternal ()
388 ArrayList selected = null;
391 if (items != null && (count = items.Count) > 0) {
392 selected = new ArrayList ();
393 for (int i = 0; i < count; i++) {
394 if (items [i].Selected)
401 protected override object SaveViewState ()
403 object baseState = null;
404 object itemsState = null;
406 baseState = base.SaveViewState ();
408 IStateManager manager = items as IStateManager;
410 itemsState = manager.SaveViewState ();
412 // .NET 2.0+ never returns null. It returns a Triplet with the Third member
413 // set to an instance of ArrayList. Since we don't have a use (at least atm)
414 // for this, we will just return a pair with both members null.
415 return new Pair (baseState, itemsState);
418 protected override void LoadViewState (object savedState)
420 object baseState = null;
421 object itemsState = null;
423 Pair pair = savedState as Pair;
425 baseState = pair.First;
426 itemsState = pair.Second;
429 base.LoadViewState (baseState);
431 if (itemsState != null) {
432 IStateManager manager = Items as IStateManager;
433 manager.LoadViewState (itemsState);
437 [MonoTODO ("Not implemented")]
438 protected void SetPostDataSelection (int selectedIndex)
440 throw new NotImplementedException ();
443 protected override void TrackViewState ()
445 base.TrackViewState ();
446 IStateManager manager = items as IStateManager;
448 manager.TrackViewState ();
451 protected virtual void OnSelectedIndexChanged (EventArgs e)
453 EventHandler handler = (EventHandler) Events [SelectedIndexChangedEvent];
458 protected internal virtual void VerifyMultiSelect ()
460 if (!MultiSelectOk ())
461 throw new HttpException("Multi select is not supported");
464 internal virtual bool MultiSelectOk ()
469 [WebSysDescription ("")]
470 [WebCategory ("Action")]
471 public event EventHandler SelectedIndexChanged {
472 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
473 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
476 /* sealed in the docs */
477 public event EventHandler TextChanged {
479 Events.AddHandler (TextChangedEvent, value);
482 Events.RemoveHandler (TextChangedEvent, value);
488 [DefaultValue (false)]
489 [WebSysDescription ("")]
490 [WebCategory ("Behavior")]
491 public virtual bool CausesValidation {
493 return ViewState.GetBool ("CausesValidation", false);
497 ViewState ["CausesValidation"] = value;
503 [WebSysDescription ("")]
504 [WebCategoryAttribute ("Behavior")]
505 public virtual string ValidationGroup {
507 return ViewState.GetString ("ValidationGroup", "");
510 ViewState ["ValidationGroup"] = value;