* Style.cs: fixed restoring FontInfo from ViewState
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / BaseDataList.cs
old mode 100755 (executable)
new mode 100644 (file)
index 11caf97..02a27c3
-/**\r
- * Namespace: System.Web.UI.WebControls\r
- * Class:     BaseDataList\r
- *\r
- * Author:  Gaurav Vaish\r
- * Maintainer: gvaish@iitk.ac.in\r
- * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>\r
- * Status:  20%\r
- *\r
- * (C) Gaurav Vaish (2001)\r
- */\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Web;\r
-using System.Web.UI;\r
-\r
-namespace System.Web.UI.WebControls\r
-{\r
-       public abstract class BaseDataList: WebControl\r
-       {\r
-\r
-               private int cellPadding = -1;\r
-               private int cellSpacing = 0;\r
-               private object dataSource = null;\r
-               private string dataKeyField = String.Empty;\r
-               private DataKeyCollection dataKeys;             // TODO: From where do get the values into it?\r
-               private string dataMember;\r
-               private GridLines gridLines;\r
-               private HorizontalAlign hAlign;\r
-\r
-               public BaseDataList()\r
-               {\r
-                       // TODO Something\r
-                       dataKeys = new DataKeyCollection(new ArrayList());\r
-                       dataMember = String.Empty;\r
-                       gridLines = GridLines.Both;\r
-                       hAlign = HorizontalAlign.NotSet;\r
-               }\r
-\r
-               public static bool IsBindableType(Type type)\r
-               {\r
-                       //TODO: To see what has to be here\r
-                       if(type.IsPrimitive)\r
-                       {\r
-                               //Type.GetTypeFromHandle(new RuntimeTypeHandle());\r
-                       }\r
-                       return false; //for the time being, to be able to make it compile\r
-               }\r
-\r
-               public virtual int CellPadding\r
-               {\r
-                       get\r
-                       {\r
-                               return cellPadding;\r
-                       }\r
-                       set\r
-                       {\r
-                               cellPadding = value;\r
-                       }\r
-               }\r
-\r
-               public virtual int CellSpacing\r
-               {\r
-                       get\r
-                       {\r
-                               return cellSpacing;\r
-                       }\r
-                       set\r
-                       {\r
-                               cellSpacing = value;\r
-                       }\r
-               }\r
-\r
-               public virtual string DataKeyField\r
-               {\r
-                       get\r
-                       {\r
-                               return dataKeyField;\r
-                       }\r
-                       set\r
-                       {\r
-                               dataKeyField = value;\r
-                       }\r
-               }\r
-\r
-               public DataKeyCollection DataKeys\r
-               {\r
-                       get\r
-                       {\r
-                               return dataKeys;\r
-                       }\r
-               }\r
-\r
-               public string DataMember\r
-               {\r
-                       get\r
-                       {\r
-                               return dataMember;\r
-                       }\r
-                       set\r
-                       {\r
-                               dataMember = value;\r
-                       }\r
-               }\r
-\r
-               public virtual object DataSource\r
-               {\r
-                       get\r
-                       {\r
-                               return dataSource;\r
-                       }\r
-                       set\r
-                       {\r
-                               dataSource = value;\r
-                       }\r
-               }\r
-\r
-               public virtual GridLines GridLines\r
-               {\r
-                       get\r
-                       {\r
-                               return gridLines;\r
-                       }\r
-                       set\r
-                       {\r
-                               gridLines = value;\r
-                       }\r
-               }\r
-\r
-               public virtual HorizontalAlign HorizontalAlign\r
-               {\r
-                       get\r
-                       {\r
-                               return hAlign;\r
-                       }\r
-                       set\r
-                       {\r
-                               hAlign = value;\r
-                       }\r
-               }\r
-\r
-               public override void DataBind()\r
-               {\r
-                       // TODO: have to write the implementation\r
-                       // I am not sure of whether it will be of any use here since\r
-                       // I am an abstract class, and have no identity of myself.\r
-                       //dataBindEventArgs = EventArgs.Empty;\r
-                       OnDataBinding(EventArgs.Empty);\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               //TODO: Check - where are the following abstract methods?\r
-               /*\r
-                * CreateControlHierarchy(bool)\r
-                * PrepareControlHierarchy()\r
-               */\r
-\r
-               protected override void AddParsedSubObject(object o)\r
-               {\r
-                       // Preventing literal controls from being added as children: Do nothing here.\r
-               }\r
-\r
-               protected override void CreateChildControls()\r
-               {\r
-                       Controls.Clear();\r
-                       if(ViewState["_!ItemCount"]!=null)\r
-                       {\r
-                               CreateControlHierarchy(true);\r
-                               ClearChildViewState();\r
-                       }\r
-               }\r
-\r
-               protected abstract void CreateControlHierarchy(bool useDataSource);\r
-       }\r
-}\r
+//
+// System.Web.UI.WebControls.BaseDataList.cs
+//
+// Author:
+//     Sebastien Pouliot  <sebastien@ximian.com>
+//
+// 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.Collections;
+using System.ComponentModel;
+using System.Security.Permissions;
+
+namespace System.Web.UI.WebControls {
+
+       // CAS
+       [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+       [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+       // attributes
+       [DefaultEvent ("SelectedIndexChanged")]
+       [DefaultProperty ("DataSource")]
+       [Designer ("System.Web.UI.Design.WebControls.BaseDataListDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
+       public abstract class BaseDataList : WebControl {
+
+               private static readonly object selectedIndexChangedEvent = new object ();
+
+               private DataKeyCollection keycoll;
+               private object source;
+#if NET_2_0
+               //private string dataSourceId;
+               IDataSource boundDataSource = null;
+               private bool initialized;
+               private bool requiresDataBinding;
+               private DataSourceSelectArguments selectArguments;
+               private IEnumerable data;
+#endif
+
+               protected BaseDataList ()
+               {
+               }
+
+
+               [DefaultValue ("")]
+#if NET_2_0
+               [Localizable (true)]
+#endif
+               [WebSysDescription ("")]
+               [WebCategory ("Accessibility")]
+               public virtual string Caption {
+                       get { return ViewState.GetString ("Caption", ""); }
+                       set {
+                               if (value == null)
+                                       ViewState.Remove ("Caption");
+                               else
+                                       ViewState ["Caption"] = value;
+                       }
+               }
+
+               [DefaultValue (TableCaptionAlign.NotSet)]
+               public virtual TableCaptionAlign CaptionAlign {
+                       get { return (TableCaptionAlign) ViewState.GetInt ("CaptionAlign", (int)TableCaptionAlign.NotSet); }
+                       set {
+                               if ((value < TableCaptionAlign.NotSet) || (value > TableCaptionAlign.Right))
+                                       throw new ArgumentOutOfRangeException (Locale.GetText ("Invalid TableCaptionAlign value."));
+
+                               ViewState ["CaptionAlign"] = value;
+                       }
+               }
+
+#if ONLY_1_1
+               [Bindable (true)]
+#endif
+               [DefaultValue (-1)]
+               [WebSysDescription("")]
+               [WebCategory("Layout")]
+               public virtual int CellPadding {
+                       get {
+                               if (!ControlStyleCreated)
+                                       return -1; // default value
+                               return TableStyle.CellPadding;
+                       }
+                       set { TableStyle.CellPadding = value; }
+               }
+
+#if ONLY_1_1
+               [Bindable (true)]
+#endif
+               [DefaultValue (0)]
+               [WebSysDescription("")]
+               [WebCategory("Layout")]
+               public virtual int CellSpacing {
+                       get {
+                               if (!ControlStyleCreated)
+                                       return 0; // default value
+                               return TableStyle.CellSpacing;
+                       }
+                       set { TableStyle.CellSpacing = value; }
+               }
+
+               public override ControlCollection Controls {
+                       get {
+                               EnsureChildControls ();
+                               return base.Controls;
+                       }
+               }
+
+               [DefaultValue ("")]
+#if NET_2_0
+               [Themeable (false)]
+#endif
+               [MonoTODO ("incomplete")]
+               [WebSysDescription("")]
+               [WebCategory("Data")]
+               public virtual string DataKeyField {
+                       get { return ViewState.GetString ("DataKeyField", ""); }
+                       set {
+                               if (value == null)
+                                       ViewState.Remove ("DataKeyField");
+                               else
+                                       ViewState ["DataKeyField"] = value;
+                       }
+               }
+
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               [WebSysDescription("")]
+               [WebCategory("Data")]
+               public DataKeyCollection DataKeys {
+                       get {
+                               if (keycoll == null)
+                                       keycoll = new DataKeyCollection (DataKeysArray);
+                               return keycoll;
+                       }
+               }
+
+               protected ArrayList DataKeysArray {
+                       get {
+                               ArrayList keys = (ArrayList) ViewState ["DataKeys"];
+                               if (keys == null) {
+                                       keys = new ArrayList ();
+                                       ViewState ["DataKeys"] = keys;
+                               }
+                               return keys;
+                       }
+               }
+
+               [DefaultValue ("")]
+#if NET_2_0
+               [Themeable (false)]
+#endif
+               [WebSysDescription("")]
+               [WebCategory("Data")]
+               public string DataMember {
+                       get { return ViewState.GetString ("DataMember", ""); }
+                       set {
+                               if (value == null)
+                                       ViewState.Remove ("DataMember");
+                               else
+                                       ViewState ["DataMember"] = value;
+#if NET_2_0
+                               if (!Initialized)
+                                       OnDataPropertyChanged ();
+#endif
+                       }
+               }
+
+               [Bindable (true)]
+               [DefaultValue (null)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+#if NET_2_0
+               [Themeable (false)]
+#endif
+               [WebSysDescription("")]
+               [WebCategory("Data")]
+               public virtual object DataSource {
+                       get { return source; }
+                       set {
+                               if ((value == null) || (value is IEnumerable) || (value is IListSource)) {
+#if NET_2_0
+// FIXME - can't duplicate in a test case ? LAMESPEC ?
+// can't duplicate in a test case
+//                                     if ((dataSourceId != null) && (dataSourceId.Length != 0))
+//                                             throw new HttpException (Locale.GetText ("DataSourceID is already set."));
+
+                                       source = value;
+
+                                       if (!Initialized)
+                                               OnDataPropertyChanged ();
+#else
+                                       source = value;
+#endif
+                               } else {
+                                       string msg = Locale.GetText ("Invalid data source. This requires an object implementing {0} or {1}.",
+                                               "IEnumerable", "IListSource");
+                                       throw new ArgumentException (msg);
+                               }
+                       }
+               }
+
+#if ONLY_1_1
+               [Bindable (true)]
+#endif
+               [DefaultValue (GridLines.Both)]
+               [WebSysDescription("")]
+               [WebCategory("Appearance")]
+               public virtual GridLines GridLines {
+                       get {
+                               if (!ControlStyleCreated)
+                                       return GridLines.Both; // default value
+                               return TableStyle.GridLines;
+                       }
+                       set { TableStyle.GridLines = value; }
+               }
+
+#if ONLY_1_1
+               [Bindable (true)]
+#endif
+               [Category ("Layout")]
+               [DefaultValue (HorizontalAlign.NotSet)]
+               [WebSysDescription("")]
+               public virtual HorizontalAlign HorizontalAlign {
+                       get {
+                               if (!ControlStyleCreated)
+                                       return HorizontalAlign.NotSet; // default value
+                               return TableStyle.HorizontalAlign;
+                       }
+                       set { TableStyle.HorizontalAlign = value; }
+               }
+
+               [DefaultValue (false)]
+               public virtual bool UseAccessibleHeader {
+                       get { return ViewState.GetBool ("UseAccessibleHeader", false); }
+                       set { ViewState ["UseAccessibleHeader"] = value; }
+               }
+#if NET_2_0
+               [DefaultValue ("")]
+               [IDReferenceProperty (typeof (DataSourceControl))]
+               [Themeable (false)]
+               public virtual string DataSourceID {
+                       get { return ViewState.GetString ("DataSourceID", ""); }
+                       set {
+                               // LAMESPEC ? this is documented as an HttpException in beta2
+                               if (source != null)
+                                       throw new InvalidOperationException (Locale.GetText ("DataSource is already set."));
+
+                               ViewState ["DataSourceID"] = value;
+
+                               if (!Initialized)
+                                       OnDataPropertyChanged ();
+                       }
+               }
+
+               protected bool Initialized {
+                       get { return initialized; }
+               }
+
+               // as documented in BaseDataBoundControl
+               protected bool IsBoundUsingDataSourceID {
+                       get { return (DataSourceID.Length != 0); }
+               }
+
+               // doc says ?automatically? called by ASP.NET
+               protected bool RequiresDataBinding {
+                       get { return requiresDataBinding; }
+                       set { requiresDataBinding = value; }
+               }
+
+               protected DataSourceSelectArguments SelectArguments {
+                       get {
+                               if (selectArguments == null)
+                                       selectArguments = CreateDataSourceSelectArguments ();
+                               return selectArguments;
+                       }
+               }
+#endif
+               private TableStyle TableStyle {
+                       // this will throw an InvalidCasException just like we need
+                       get { return (TableStyle) ControlStyle; }
+               }
+
+
+               protected override void AddParsedSubObject (object obj)
+               {
+                       // don't accept controls
+               }
+
+               // see Kothari, page 435
+#if NET_2_0
+               protected internal
+#else          
+               protected
+#endif         
+               override void CreateChildControls ()
+               {
+                       // We are recreating the children from viewstate
+                       if (HasControls ())
+                               Controls.Clear();
+
+                       // If presents, build the children from the viewstate
+                       if (ViewState ["Items"] != null)
+                               CreateControlHierarchy (false);
+               }
+
+               protected abstract void CreateControlHierarchy (bool useDataSource);
+
+               // see Kothari, page 434
+               // see also: Control.DataBind on Fx 2.0 beta2 documentation
+               public override void DataBind ()
+               {
+                       // unlike most samples we don't call base.OnDataBinding
+                       // because we override it in this class
+                       OnDataBinding (EventArgs.Empty);
+
+                       // Clear, if required, then recreate the control hierarchy
+                       if (HasControls ())
+                               Controls.Clear ();
+                       if (HasChildViewState)
+                               ClearChildViewState ();
+                       if (!IsTrackingViewState)
+                               TrackViewState ();
+                       CreateControlHierarchy (true);
+
+                       // Indicate that child controls have been created, preventing
+                       // CreateChildControls from getting called.
+                       ChildControlsCreated = true;    
+               }
+#if NET_2_0
+               protected virtual DataSourceSelectArguments CreateDataSourceSelectArguments ()
+               {
+                       return DataSourceSelectArguments.Empty;
+               }
+
+               // best documentation is (again) in BaseDataBoundControl
+               protected void EnsureDataBound ()
+               {
+                       if (IsBoundUsingDataSourceID && RequiresDataBinding)
+                               DataBind ();
+               }
+
+               private void SelectCallback (IEnumerable data)
+               {
+                       this.data = data;
+               }
+
+               protected virtual IEnumerable GetData ()
+               {
+                       if (DataSourceID.Length == 0)
+                               return null;
+
+                       if (boundDataSource == null)
+                               ConnectToDataSource ();
+
+                       DataSourceView dsv = boundDataSource.GetView (String.Empty);
+                       dsv.Select (SelectArguments, new DataSourceViewSelectCallback (SelectCallback));
+                       return data;
+               }
+#endif
+
+               protected override void OnDataBinding (EventArgs e)
+               {
+                       base.OnDataBinding (e);
+               }
+#if NET_2_0
+               protected virtual void OnDataPropertyChanged ()
+               {
+               }
+
+               protected virtual void OnDataSourceViewChanged (object sender, EventArgs e)
+               {
+                       RequiresDataBinding = true;
+               }
+
+               protected internal override void OnInit (EventArgs e)
+               {
+                       base.OnInit (e);
+               }
+
+               protected internal override void OnLoad (EventArgs e)
+               {
+                       if ((Page != null) && !Page.IsPostBack)
+                               RequiresDataBinding = true;
+
+                       if (IsBoundUsingDataSourceID)
+                               ConnectToDataSource ();
+
+                       initialized = true;
+                       base.OnLoad (e);
+               }
+
+               protected internal override void OnPreRender (EventArgs e)
+               {
+                       EnsureDataBound ();
+                       base.OnPreRender (e);
+               }
+#endif
+               protected virtual void OnSelectedIndexChanged (EventArgs e)
+               {
+                       EventHandler selectedIndexChanged = (EventHandler) Events [selectedIndexChangedEvent];
+                       if (selectedIndexChanged != null)
+                               selectedIndexChanged (this, e);
+               }
+
+               protected abstract void PrepareControlHierarchy ();
+
+#if NET_2_0
+               protected internal
+#else          
+               protected
+#endif         
+               override void Render (HtmlTextWriter writer)
+               {
+                       PrepareControlHierarchy ();
+                       // don't call base class or RenderBegin|EndTag
+                       // or we'll get an extra <span></span>
+                       RenderContents (writer);
+               }
+
+
+               [WebSysDescription("")]
+               [WebCategory("Action")]
+               public event EventHandler SelectedIndexChanged {
+                       add { Events.AddHandler (selectedIndexChangedEvent, value); }
+                       remove { Events.RemoveHandler (selectedIndexChangedEvent, value); }
+               }
+
+
+               static public bool IsBindableType (Type type)
+               {
+                       // I can't believe how many NRE are possible in System.Web
+                       if (type == null) // Type.GetTypeCode no longer throws when a null is passed.
+                               throw new NullReferenceException ();
+
+                       switch (Type.GetTypeCode (type)) {
+                       case TypeCode.Boolean:
+                       case TypeCode.Byte:
+                       case TypeCode.SByte:
+                       case TypeCode.Int16:
+                       case TypeCode.UInt16:
+                       case TypeCode.Int32:
+                       case TypeCode.UInt32:
+                       case TypeCode.Int64:
+                       case TypeCode.UInt64:
+                       case TypeCode.Char:
+                       case TypeCode.Double:
+                       case TypeCode.Single:
+                       case TypeCode.DateTime:
+                       case TypeCode.Decimal:
+                       case TypeCode.String:
+                               return true;
+                       default:
+                               return false;
+                       }
+               }
+
+#if NET_2_0
+               void ConnectToDataSource ()
+               {
+                       if (NamingContainer != null)
+                               boundDataSource = (NamingContainer.FindControl (DataSourceID) as IDataSource);
+
+                       if (boundDataSource == null) {
+                               if (Parent != null)
+                                       boundDataSource = (Parent.FindControl (DataSourceID) as IDataSource);
+
+                               if (boundDataSource == null)
+                                       throw new HttpException (Locale.GetText ("Coulnd't find a DataSource named '{0}'.", DataSourceID));
+                       }
+                       DataSourceView dsv = boundDataSource.GetView (String.Empty);
+                       dsv.DataSourceViewChanged += new EventHandler (OnDataSourceViewChanged);
+               }
+#endif
+       }
+}