Merge pull request #1155 from steffen-kiess/json-string
[mono.git] / mcs / class / System.Web / System.Web.UI.HtmlControls / HtmlSelect.cs
index dfec4a6adb4ec89151d905e59829497a33abb120..5416e3af666aa2834319955581f9ef419569c64a 100644 (file)
@@ -4,7 +4,7 @@
 // Author:
 //     Dick Porter  <dick@ximian.com>
 //
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2010 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
@@ -43,17 +43,17 @@ namespace System.Web.UI.HtmlControls
        [DefaultEvent ("ServerChange")]
        [ValidationProperty ("Value")]
        [ControlBuilder (typeof (HtmlSelectBuilder))]
-#if NET_2_0
        [SupportsEventValidation]
-       public class HtmlSelect : HtmlContainerControl, IPostBackDataHandler, IParserAccessor {
-
-               DataSourceView boundDataSourceView;
-               IDataSource boundDataSource;
-               private bool requiresDataBinding;
-               IEnumerable data;
-#else
-       public class HtmlSelect : HtmlContainerControl, IPostBackDataHandler {
-#endif
+       public class HtmlSelect : HtmlContainerControl, IPostBackDataHandler, IParserAccessor
+       {
+               static readonly object EventServerChange = new object ();
+
+               DataSourceView _boundDataSourceView;
+               bool requiresDataBinding;
+               bool _initialized;
+               object datasource;
+               ListItemCollection items;
+
                public HtmlSelect () : base ("select")
                {
                }
@@ -62,8 +62,7 @@ namespace System.Web.UI.HtmlControls
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [WebSysDescription("")]
                [WebCategory("Data")]
-               public virtual string DataMember 
-               {
+               public virtual string DataMember {
                        get {
                                string member = Attributes["datamember"];
 
@@ -81,15 +80,12 @@ namespace System.Web.UI.HtmlControls
                                }
                        }
                }
-
-               object datasource;
                
                [DefaultValue (null)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [WebSysDescription("")]
                [WebCategory("Data")]
-               public virtual object DataSource 
-               {
+               public virtual object DataSource {
                        get {
                                return (datasource);
                        }
@@ -104,29 +100,26 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-#if NET_2_0
                [DefaultValue ("")]
-               public virtual string DataSourceID
-               {
+               public virtual string DataSourceID {
                        get {
                                return ViewState.GetString ("DataSourceID", "");
                        }
                        set {
-                               if (datasource != null)
-                                       throw new HttpException ("Only one of DataSource and DataSourceID can be specified.");
+                               if (DataSourceID == value)
+                                       return;
                                ViewState ["DataSourceID"] = value;
-
+                               if (_boundDataSourceView != null)
+                                       _boundDataSourceView.DataSourceViewChanged -= OnDataSourceViewChanged;
+                               _boundDataSourceView = null;
                                OnDataPropertyChanged ();
                        }
                }
-#endif
-                               
 
                [DefaultValue ("")]
                [WebSysDescription("")]
                [WebCategory("Data")]
-               public virtual string DataTextField 
-               {
+               public virtual string DataTextField {
                        get {
                                string text = Attributes["datatextfield"];
 
@@ -148,8 +141,7 @@ namespace System.Web.UI.HtmlControls
                [DefaultValue ("")]
                [WebSysDescription("")]
                [WebCategory("Data")]
-               public virtual string DataValueField 
-               {
+               public virtual string DataValueField {
                        get {
                                string value = Attributes["datavaluefield"];
 
@@ -168,8 +160,7 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-               public override string InnerHtml 
-               {
+               public override string InnerHtml {
                        get {
                                throw new NotSupportedException ();
                        }
@@ -178,8 +169,7 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-               public override string InnerText
-               {
+               public override string InnerText {
                        get {
                                throw new NotSupportedException ();
                        }
@@ -188,24 +178,20 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-#if NET_2_0
-               protected bool IsBoundUsingDataSourceID 
-               {
+               protected bool IsBoundUsingDataSourceID {
                        get {
                                return (DataSourceID.Length != 0);
                        }
                }
-#endif         
-
-               ListItemCollection items;
                
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
-               public ListItemCollection Items 
-               {
+               public ListItemCollection Items {
                        get {
                                if (items == null) {
                                        items = new ListItemCollection ();
+                                       if (IsTrackingViewState)
+                                               ((IStateManager) items).TrackViewState ();
                                }
 
                                return (items);
@@ -216,8 +202,7 @@ namespace System.Web.UI.HtmlControls
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [WebSysDescription("")]
                [WebCategory("Behavior")]
-               public bool Multiple 
-               {
+               public bool Multiple {
                        get {
                                string multi = Attributes["multiple"];
 
@@ -240,8 +225,7 @@ namespace System.Web.UI.HtmlControls
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [WebSysDescription("")]
                [WebCategory("Behavior")]
-               public string Name 
-               {
+               public string Name {
                        get {
                                return (UniqueID);
                        }
@@ -250,18 +234,14 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-#if NET_2_0
-               protected bool RequiresDataBinding 
-               {
+               protected bool RequiresDataBinding {
                        get { return requiresDataBinding; }
                        set { requiresDataBinding = value; }
                }
-#endif
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
-               public virtual int SelectedIndex 
-               {
+               public virtual int SelectedIndex {
                        get {
                                /* Make sure Items has been initialised */
                                ListItemCollection listitems = Items;
@@ -310,8 +290,7 @@ namespace System.Web.UI.HtmlControls
                /* "internal infrastructure" according to the docs,
                 * but has some documentation in 2.0
                 */
-               protected virtual int[] SelectedIndices
-               {
+               protected virtual int[] SelectedIndices {
                        get {
                                ArrayList selected = new ArrayList ();
 
@@ -329,8 +308,7 @@ namespace System.Web.UI.HtmlControls
                
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public int Size 
-               {
+               public int Size {
                        get {
                                string size = Attributes["size"];
 
@@ -338,7 +316,7 @@ namespace System.Web.UI.HtmlControls
                                        return (-1);
                                }
 
-                               return (Int32.Parse (size, CultureInfo.InvariantCulture));
+                               return (Int32.Parse (size, Helpers.InvariantCulture));
                        }
                        set {
                                if (value == -1) {
@@ -350,8 +328,7 @@ namespace System.Web.UI.HtmlControls
                }
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public string Value 
-               {
+               public string Value {
                        get {
                                int sel = SelectedIndex;
 
@@ -370,12 +347,9 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-               private static readonly object EventServerChange = new object ();
-               
                [WebSysDescription("")]
                [WebCategory("Action")]
-               public event EventHandler ServerChange
-               {
+               public event EventHandler ServerChange {
                        add {
                                Events.AddHandler (EventServerChange, value);
                        }
@@ -415,47 +389,40 @@ namespace System.Web.UI.HtmlControls
                        return (base.CreateControlCollection ());
                }
 
-#if NET_2_0
                protected void EnsureDataBound ()
                {
                        if (IsBoundUsingDataSourceID && RequiresDataBinding)
                                DataBind ();
                }
 
-               private void SelectCallback (IEnumerable data)
-               {
-                       this.data = data;
-               }
-
                protected virtual IEnumerable GetData ()
                {
-                       IEnumerable result;
+                       if (DataSource != null && IsBoundUsingDataSourceID)
+                               throw new HttpException ("Control bound using both DataSourceID and DataSource properties.");
+
+                       if (DataSource != null)
+                               return DataSourceResolver.ResolveDataSource (DataSource, DataMember);
 
-                       if (DataSourceID.Length == 0)
+                       if (!IsBoundUsingDataSourceID)
                                return null;
 
-                       boundDataSourceView = boundDataSource.GetView (String.Empty);
-                       boundDataSourceView.Select (new DataSourceSelectArguments (), SelectCallback);
-                       boundDataSourceView.DataSourceViewChanged += OnDataSourceViewChanged;
+                       IEnumerable result = null;
 
-                       result = data;
-                       data = null;
+                       DataSourceView boundDataSourceView = ConnectToDataSource ();
+                       boundDataSourceView.Select (DataSourceSelectArguments.Empty, delegate (IEnumerable data) { result = data; });
 
                        return result;
                }
-#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[];
+                       Pair pair = savedState as Pair;
+                       if (pair != null) {
+                               first = pair.First;
+                               second = pair.Second;
                        }
 
                        base.LoadViewState (first);
@@ -464,10 +431,6 @@ namespace System.Web.UI.HtmlControls
                                IStateManager manager = Items as IStateManager;
                                manager.LoadViewState (second);
                        }
-
-                       if (selected != null) {
-                               Select (selected);
-                       }
                }
 
                protected override void OnDataBinding (EventArgs e)
@@ -479,18 +442,9 @@ namespace System.Web.UI.HtmlControls
 
                        listitems.Clear ();
                        
-                       IEnumerable list;
-
-#if NET_2_0
-                       if (IsBoundUsingDataSourceID)
-                               list = GetData ();
-                       else
-#endif
-                               list = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
-
-                       if (list == null) {
+                       IEnumerable list = GetData ();
+                       if (list == null)
                                return;
-                       }
                        
                        foreach (object container in list) {
                                string text = null;
@@ -527,45 +481,72 @@ namespace System.Web.UI.HtmlControls
                                ListItem item = new ListItem (text, value);
                                listitems.Add (item);
                        }
+                       RequiresDataBinding = false;
+                       IsDataBound = true;
                }
 
-#if NET_2_0
-               [MonoTODO]
                protected virtual void OnDataPropertyChanged ()
                {
+                       if (_initialized)
                        RequiresDataBinding = true;
                }
 
-               [MonoTODO]
                protected virtual void OnDataSourceViewChanged (object sender,
                                                                EventArgs e)
                {
                        RequiresDataBinding = true;
                }
 
-               [MonoTODO]
                protected internal override void OnInit (EventArgs e)
                {
                        base.OnInit (e);
+
+                       Page.PreLoad += new EventHandler (OnPagePreLoad);
+               }
+
+               protected virtual void OnPagePreLoad (object sender, EventArgs e)
+               {
+                       Initialize ();
                }
 
                protected internal override void OnLoad (EventArgs e)
                {
-                       if ((Page != null) && !Page.IsPostBack)
-                               RequiresDataBinding = true;
+                       if (!_initialized)
+                               Initialize ();
 
                        base.OnLoad (e);
+               }
+
+               void Initialize ()
+               {
+                       _initialized = true;
+
+                       if (!IsDataBound)
+                               RequiresDataBinding = true;
 
                        if (IsBoundUsingDataSourceID)
                                ConnectToDataSource ();
                }
 
-               void ConnectToDataSource ()
+               bool IsDataBound{
+                       get {
+                               return ViewState.GetBool ("_DataBound", false);
+                       }
+                       set {
+                               ViewState ["_DataBound"] = value;
+                       }
+               }
+
+               DataSourceView ConnectToDataSource ()
                {
+                       if (_boundDataSourceView != null)
+                               return _boundDataSourceView;
+
                        /* verify that the data source exists and is an IDataSource */
                        object ctrl = null;
-                       if (Page != null)
-                               ctrl = Page.FindControl (DataSourceID);
+                       Page page = Page;
+                       if (page != null)
+                               ctrl = page.FindControl (DataSourceID);
 
                        if (ctrl == null || !(ctrl is IDataSource)) {
                                string format;
@@ -578,25 +559,20 @@ namespace System.Web.UI.HtmlControls
                                throw new HttpException (String.Format (format, ID, DataSourceID));
                        }
 
-                       boundDataSource = (IDataSource)ctrl;
+                       _boundDataSourceView = ((IDataSource)ctrl).GetView (String.Empty);
+                       _boundDataSourceView.DataSourceViewChanged += OnDataSourceViewChanged;
+                       return _boundDataSourceView;
                }
-#endif
 
-#if NET_2_0
-               protected internal
-#else          
-               protected
-#endif         
-               override void OnPreRender (EventArgs e)
+               protected internal override void OnPreRender (EventArgs e)
                {
-#if NET_2_0
                        EnsureDataBound ();
-#endif
-
                        base.OnPreRender (e);
 
-                       if (Page != null) {
-                               Page.RegisterRequiresPostBack (this);
+                       Page page = Page;
+                       if (page != null && !Disabled) {
+                               page.RegisterRequiresPostBack (this);
+                               page.RegisterEnabledControl (this);
                        }
                }
 
@@ -611,6 +587,10 @@ namespace System.Web.UI.HtmlControls
                
                protected override void RenderAttributes (HtmlTextWriter w)
                {
+                       Page page = Page;
+                       if (page != null)
+                               page.ClientScript.RegisterForEventValidation (UniqueID);
+
                        /* If there is no "name" attribute,
                         * LoadPostData doesn't work...
                         */
@@ -625,18 +605,12 @@ namespace System.Web.UI.HtmlControls
                        base.RenderAttributes (w);
                }
                
-#if NET_2_0
-               protected internal
-#else
-               protected
-#endif         
-               override void RenderChildren (HtmlTextWriter w)
+               protected internal override void RenderChildren (HtmlTextWriter w)
                {
                        base.RenderChildren (w);
 
-                       if (items == null) {
+                       if (items == null)
                                return;
-                       }
                        
                        w.WriteLine ();
 
@@ -645,7 +619,6 @@ namespace System.Web.UI.HtmlControls
                        int count = items.Count;
                        for (int i = 0; i < count; i++) {
                                ListItem item = items[i];
-
                                w.Indent++;
                                
                                /* Write the <option> elements this
@@ -665,10 +638,15 @@ namespace System.Web.UI.HtmlControls
                                        }
                                }
                                
-                               w.WriteAttribute ("value", item.Value);
+                               w.WriteAttribute ("value", item.Value, true);
+                               if (item.HasAttributes) {
+                                       AttributeCollection attrs = item.Attributes;
+                                       foreach (string key in attrs.Keys)
+                                               w.WriteAttribute (key, HttpUtility.HtmlAttributeEncode (attrs [key]));
+                               }
                                w.Write (HtmlTextWriter.TagRightChar);
                                
-                               w.Write (item.Text);
+                               w.Write (HttpUtility.HtmlEncode(item.Text));
                                w.WriteEndTag ("option");
                                w.WriteLine ();
 
@@ -680,7 +658,6 @@ namespace System.Web.UI.HtmlControls
                {
                        object first = null;
                        object second = null;
-                       object selected = null;
 
                        first = base.SaveViewState ();
 
@@ -689,15 +666,10 @@ namespace System.Web.UI.HtmlControls
                                second = manager.SaveViewState ();
                        }
 
-                       selected = SelectedIndices;
-                       
-                       if (first == null &&
-                           second == null &&
-                           selected == null) {
+                       if (first == null && second == null)
                                return (null);
-                       }
 
-                       return (new Triplet (first, second, selected));
+                       return new Pair (first, second);
                }
 
                /* "internal infrastructure" according to the docs,
@@ -729,19 +701,12 @@ namespace System.Web.UI.HtmlControls
                        }
                }
 
-#if NET_2_0
-               protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection) 
-               {
-                       return (LoadPostData (postDataKey, postCollection));
-               }
-
                protected virtual void RaisePostDataChangedEvent ()
                {
-                       RaisePostDataChangedEvent ();
+                       OnServerChange (EventArgs.Empty);
                }
-#endif
 
-               bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
+               protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
                {
                        /* postCollection contains the values that are
                         * selected
@@ -784,14 +749,20 @@ namespace System.Web.UI.HtmlControls
                                        }
                                }
                        }
-                       
+
+                       if (changed)
+                               ValidateEvent (postDataKey, String.Empty);
                        return (changed);
                }
 
+               bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
+               {
+                       return LoadPostData (postDataKey, postCollection);
+               }
+
                void IPostBackDataHandler.RaisePostDataChangedEvent ()
                {
-                       OnServerChange (EventArgs.Empty);
+                       RaisePostDataChangedEvent ();
                }
-               
        }
 }