Pārlūkot izejas kodu

2002-07-17 Gonzalo Paniagua Javier <[email protected]>

	* Control.cs: fixed related to ViewState. Added RemovedControl.

	* ControlCollection.cs: notify owner of control removal.

	* CssStyleCollection.cs: almost rewritten to make it render the style
	attribute after changes to it.

	* Page.cs: follow the guidelines in 'Control execution lifecycle'.
	Removed Xml code.

	* StateBag.cs: don't use IDictionary.GetEnumerator on the
	HybridDictionary: it makes the program give an InvalidCastException at
	runtime. Why?

svn path=/trunk/mcs/; revision=5863
Gonzalo Paniagua Javier 23 gadi atpakaļ
vecāks
revīzija
d2e41bdda3

+ 16 - 0
mcs/class/System.Web/System.Web.UI/ChangeLog

@@ -1,3 +1,19 @@
+2002-07-17  Gonzalo Paniagua Javier <[email protected]>
+
+	* Control.cs: fixed related to ViewState. Added RemovedControl.
+
+	* ControlCollection.cs: notify owner of control removal.
+	
+	* CssStyleCollection.cs: almost rewritten to make it render the style
+	attribute after changes to it.
+
+	* Page.cs: follow the guidelines in 'Control execution lifecycle'.
+	Removed Xml code.
+
+	* StateBag.cs: don't use IDictionary.GetEnumerator on the
+	HybridDictionary: it makes the program give an InvalidCastException at
+	runtime. Why?
+
 2002-07-16  Gonzalo Paniagua Javier <[email protected]>
 
 	* Page.cs: fire Init and Load events for all children.

+ 60 - 21
mcs/class/System.Web/System.Web.UI/Control.cs

@@ -1,10 +1,12 @@
 //
 // System.Web.UI.Control.cs
 //
-// Author:
-//   Bob Smith <[email protected]>
+// Authors:
+// 	Bob Smith <[email protected]>
+// 	Gonzalo Paniagua Javier ([email protected])
 //
 // (C) Bob Smith
+// (c) 2002 Ximian, Inc. (http://www.ximian.com)
 //
 
 /*
@@ -311,19 +313,18 @@ namespace System.Web.UI
                         get
                         {
                         	if(_viewState == null)
-                        	{
-	                        	_viewState = new StateBag(ViewStateIgnoresCase);
-    	                    	if(IsTrackingViewState)
-        	                		_viewState.TrackViewState();
-                        	}
+	                        	_viewState = new StateBag (ViewStateIgnoresCase);
+
+				if (IsTrackingViewState)
+					_viewState.TrackViewState ();
+
                         	return _viewState;
                         }
                 }
-                protected virtual bool ViewStateIgnoresCase //DIT
+                protected virtual bool ViewStateIgnoresCase
                 {
-                        get
-                        {
-                                return true;
+                        get {
+                                return false;
                         }
                 }
 
@@ -400,7 +401,8 @@ namespace System.Web.UI
 
                 protected virtual void LoadViewState(object savedState)
                 {
-			ViewState.LoadViewState (savedState);
+			if (savedState != null)
+				ViewState.LoadViewState (savedState);
                 }
                 
 		[MonoTODO]
@@ -476,11 +478,16 @@ namespace System.Web.UI
 		
                 protected virtual object SaveViewState ()
                 {
-                        return ViewState.SaveViewState ();
+			if (_viewState == null)
+				return null;
+
+			return _viewState.SaveViewState ();
                 }
 
                 protected virtual void TrackViewState()
                 {
+			if (_viewState != null)
+				_viewState.TrackViewState ();
                         _trackViewState = true;
                 }
                 
@@ -589,8 +596,6 @@ namespace System.Web.UI
                 {
                         if (_visible)
                         {
-				// By now, PreRender is fired here.
-				OnPreRender (EventArgs.Empty); //FIXME
                                 //TODO: Something about tracing here.
                                 Render(writer);
                         }
@@ -601,38 +606,51 @@ namespace System.Web.UI
                 {
                 	return relativeUrl;
                 }
+
                 public void SetRenderMethodDelegate(RenderMethod renderMethod) //DIT
                 {
                         _renderMethodDelegate = renderMethod;
                 }
+
                 protected void LoadRecursive()
                 {
                         OnLoad(EventArgs.Empty);
                         if (_controls != null) foreach (Control c in _controls) c.LoadRecursive();
                 }
+
                 protected void UnloadRecursive(Boolean dispose)
                 {
                         OnUnload(EventArgs.Empty);
                         if (_controls != null) foreach (Control c in _controls) c.UnloadRecursive(dispose);
                         if (dispose) Dispose();
                 }
+
                 protected void PreRenderRecursiveInternal()
                 {
                         OnPreRender(EventArgs.Empty);
                         if (_controls != null) foreach (Control c in _controls) c.PreRenderRecursiveInternal();
                 }
+
                 protected void InitRecursive(Control namingContainer)
                 {
                         if (_controls != null) foreach (Control c in _controls) c.InitRecursive(namingContainer);
                         OnInit(EventArgs.Empty);
+			TrackViewState ();
                 }
                 
                 protected object SaveViewStateRecursive()
                 {
-			ArrayList controlList = new ArrayList ();
-			ArrayList controlStates = new ArrayList ();
+			if (!EnableViewState || !Visible)
+				return null;
+
+			ArrayList controlList = null;
+			ArrayList controlStates = null;
 
 			foreach (Control ctrl in Controls){
+				if (controlList == null) {
+					controlList = new ArrayList ();
+					controlStates = new ArrayList ();
+				}
 				controlList.Add (ctrl);
 				controlStates.Add (ctrl.SaveViewStateRecursive ());
 			}
@@ -640,10 +658,23 @@ namespace System.Web.UI
 			return new Triplet (SaveViewState (), controlList, controlStates);
                 }
                 
-                [MonoTODO]
-                protected void LoadViewStateRecursive(Object savedState)
-                {
-			throw new NotImplementedException ();
+                protected void LoadViewStateRecursive (object savedState)
+                {
+			if (!EnableViewState || !Visible || savedState == null)
+				return;
+
+			Triplet savedInfo = (Triplet) savedState;
+			LoadViewState (savedInfo.First);
+
+			ArrayList controlList = savedInfo.Second as ArrayList;
+			if (controlList == null)
+				return;
+			ArrayList controlStates = savedInfo.Third as ArrayList;
+			int nControls = controlList.Count;
+			for (int i = 0; i < nControls; i++) {
+				if (controlStates != null)
+					Controls [i].LoadViewStateRecursive (controlStates [i]);
+			}
                 }
                 
                 void IParserAccessor.AddParsedSubObject(object obj)
@@ -680,6 +711,14 @@ namespace System.Web.UI
 			AutoID = false;
                 }
                 
+		protected internal virtual void RemovedControl (Control control)
+		{
+			control.UnloadRecursive (false);
+			control._parent = null;
+			control._page = null;
+			control._namingContainer = null;
+		}
+
                 //TODO: I think there are some needed Interface implementations to do here.
                 //TODO: Find api for INamingContainer.
         }

+ 6 - 3
mcs/class/System.Web/System.Web.UI/ControlCollection.cs

@@ -85,7 +85,7 @@ namespace System.Web.UI {
 
 		public virtual bool Contains (Control c)
 		{
-			return list.Contains (c as object);
+			return list.Contains (c);
 		}
 
 		public void CopyTo (Array array, int index)
@@ -100,12 +100,13 @@ namespace System.Web.UI {
 
 		public virtual int IndexOf (Control c)
 		{
-			return list.IndexOf (c as object);
+			return list.IndexOf (c);
 		}
 
 		public virtual void Remove (Control value)
 		{
-			list.Remove (value as object);
+			list.Remove (value);
+			owner.RemovedControl (value);
 		}
 
 		public virtual void RemoveAt (int index)
@@ -113,7 +114,9 @@ namespace System.Web.UI {
 			if (IsReadOnly)
 				throw new HttpException ();
 
+			Control value = (Control) list [index];
 			list.RemoveAt (index);
+			owner.RemovedControl (value);
 		}
 	}
 }

+ 59 - 9
mcs/class/System.Web/System.Web.UI/CssStyleCollection.cs

@@ -10,46 +10,96 @@
 
 using System;
 using System.Collections;
+using System.Text;
 
 namespace System.Web.UI {
 
 	public sealed class CssStyleCollection
 	{
 		private StateBag bag;
+		private StateBag style;
 
 		internal CssStyleCollection (StateBag bag)
 		{
 			this.bag = bag;
+			style = new StateBag ();
+			string st_string = bag ["style"] as string;
+			if (st_string != null)
+				fillStyle (st_string);
 		}
 		
-		public int Count {
-			get { return bag.Count; }
+		private void fillStyle (string s)
+		{
+			int mark = s.IndexOf (':');
+			if (mark == -1)
+				return;
+			string key = s.Substring (0, mark). Trim ();
+			if (mark + 1 > s.Length)
+				return;
+
+			string fullValue = s.Substring (mark + 1);
+			if (fullValue == "")
+				return;
+
+			mark = fullValue.IndexOf (';');
+			string value;
+			if (mark == -1)
+				value = fullValue.Trim ();
+			else
+				value = fullValue.Substring (0, mark).Trim ();
+
+			style.Add (key, value);
+			if (mark + 1 > fullValue.Length)
+				return;
+			fillStyle (fullValue.Substring (mark + 1));
 		}
 
-		public string this [string key] {
+		private string BagToString ()
+		{
+			StringBuilder sb = new StringBuilder ();
+			foreach (string k in style.Keys)
+				sb.AppendFormat ("{0}: {1}; ", k, style [k]);
+			return sb.ToString ();
+		}
+		
+		public int Count
+		{
+			get { return style.Count; }
+		}
 
-			get { return bag [key] as string; }
+		public string this [string key]
+		{
+			get {
+				return style [key] as string;
+			}
 
-			set { bag [key] = value; }
+			set {
+				Add (key, value);
+			}
 		}
 
 		public ICollection Keys {
-			get { return bag.Keys; }
+			get { return style.Keys; }
 		}
 
 		public void Add (string key, string value)
 		{
-			bag.Add (key, value);
+			style [key] = value;
+			bag ["style"] = BagToString ();
 		}
 
 		public void Clear ()
 		{
-			bag.Clear ();
+			bag.Remove ("style");
+			style.Clear ();
 		}
 
 		public void Remove (string key)
 		{
-			bag.Remove (key);
+			if (style [key] != null) {
+				style.Remove (key);
+				bag ["style"] = BagToString ();
+			}
 		}
 	}
 }

+ 60 - 84
mcs/class/System.Web/System.Web.UI/Page.cs

@@ -18,7 +18,6 @@ using System.Text;
 using System.Web;
 using System.Web.Caching;
 using System.Web.SessionState;
-using System.Xml;
 
 namespace System.Web.UI
 {
@@ -41,11 +40,12 @@ public class Page : TemplateControl, IHttpHandler
 	private string _UICulture;
 	private HttpContext _context;
 	private ValidatorCollection _validators;
-	private bool _visible;
 	private bool _renderingForm;
 	private bool _hasForm;
 	private object _savedViewState;
 	private ArrayList _requiresPostBack;
+	private ArrayList requiresPostDataChanged;
+	private ArrayList requiresRaiseEvent;
 
 	#region Fields
 	 	protected const string postEventArgumentID = ""; //FIXME
@@ -235,8 +235,8 @@ public class Page : TemplateControl, IHttpHandler
 
 	public override bool Visible
 	{
-		get { return _visible; }
-		set { _visible = value; }
+		get { return base.Visible; }
+		set { base.Visible = value; }
 	}
 
 	#endregion
@@ -409,37 +409,30 @@ public class Page : TemplateControl, IHttpHandler
 	private void ProcessPostData ()
 	{
 		NameValueCollection data = DeterminePostBackMode ();
-		ArrayList _raisePostBack = new ArrayList ();
 
 		foreach (string id in data.AllKeys){
-			string value = data [id];
+			if (id == "__VIEWSTATE")
+				continue;
+
 			Control ctrl = FindControl (id);
 			if (ctrl != null){
 				IPostBackDataHandler pbdh = ctrl as IPostBackDataHandler;
-				IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
 				if (pbdh != null) {
 					if (pbdh.LoadPostData (id, data) == true) {
-						pbdh.RaisePostDataChangedEvent ();
-						if (pbeh == null)
-							continue;
-						if (_requiresPostBack != null &&
-						    !(_requiresPostBack.Contains (ctrl)))
-								_raisePostBack.Add (pbeh);
+						if (requiresPostDataChanged == null)
+							requiresPostDataChanged = new ArrayList ();
+						requiresPostDataChanged.Add (ctrl);
 					}
-					continue;
 				}
 
-				if (pbeh != null)
-					pbeh.RaisePostBackEvent (null);
+				IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
+				if (pbeh != null) {
+					if (requiresRaiseEvent == null)
+						requiresRaiseEvent = new ArrayList ();
+					requiresRaiseEvent.Add (ctrl);
+				}
 			}
 		}
-
-		foreach (IPostBackEventHandler e in _raisePostBack)
-			e.RaisePostBackEvent (null);
-
-		if (_requiresPostBack != null)
-			foreach (IPostBackEventHandler e in _requiresPostBack)
-				e.RaisePostBackEvent (null);
 	}
 
 	private bool init_done;
@@ -451,30 +444,53 @@ public class Page : TemplateControl, IHttpHandler
 			// This 2 should depend on AutoEventWireUp in Page directive. Defaults to true.
 			Init += new EventHandler (_Page_Init);
 			Load += new EventHandler (_Page_Load);
-
 			//-- Control execution lifecycle in the docs
-			InitRecursive (this);
+			InitRecursive (null);
 		}
 		_got_state = false;
 		_hasForm = false;
 		_context = context;
-		//LoadViewState ();
+		if (IsPostBack)
+			LoadPageViewState ();
 		//if (this is IPostBackDataHandler)
 		//	LoadPostData ();
+		
 		if (IsPostBack)
 			ProcessPostData ();
 
 		LoadRecursive ();
-		//if (this is IPostBackDataHandler)
-		//	RaisePostBackEvent ();
+		if (IsPostBack) {
+			RaiseChangedEvents ();
+			RaisePostBackEvents ();
+		}
 		PreRenderRecursiveInternal ();
 
+		SavePageViewState ();
 		//--
 		HtmlTextWriter output = new HtmlTextWriter (context.Response.Output);
-		foreach (Control ctrl in Controls)
-			ctrl.RenderControl (output);
+		this.RenderControl (output);
 
-		//SavePageViewState ();
+	}
+
+	internal void RaisePostBackEvents ()
+	{
+		if (requiresRaiseEvent == null)
+			return;
+
+		NameValueCollection postdata = DeterminePostBackMode ();
+		foreach (Control c in requiresRaiseEvent)
+			RaisePostBackEvent ((IPostBackEventHandler) c, postdata [c.ID]);
+		requiresRaiseEvent.Clear ();
+	}
+
+	internal void RaiseChangedEvents ()
+	{
+		if (requiresPostDataChanged == null)
+			return;
+
+		foreach (IPostBackDataHandler ipdh in requiresPostDataChanged)
+			ipdh.RaisePostDataChangedEvent ();
+		requiresPostDataChanged.Clear ();
 	}
 
 	protected virtual void RaisePostBackEvent (IPostBackEventHandler sourceControl, string eventArgument)
@@ -520,10 +536,11 @@ public class Page : TemplateControl, IHttpHandler
 		_requiresPostBack.Add (control);
 	}
 
-	[MonoTODO]
 	public virtual void RegisterRequiresRaiseEvent (IPostBackEventHandler control)
 	{
-		throw new NotImplementedException ();
+		if (requiresRaiseEvent == null)
+			requiresRaiseEvent = new ArrayList ();
+		requiresRaiseEvent.Add (control);
 	}
 
 	[MonoTODO]
@@ -532,10 +549,9 @@ public class Page : TemplateControl, IHttpHandler
 		// Do nothing
 	}
 
-	[MonoTODO]
-	protected virtual void SavePageStatetoPersistenceMedium (object viewState)
+	protected virtual void SavePageStateToPersistenceMedium (object viewState)
 	{
-		throw new NotImplementedException ();
+		_savedViewState = viewState;
 	}
 	
 	protected virtual object LoadPageStateFromPersistenceMedium ()
@@ -546,59 +562,19 @@ public class Page : TemplateControl, IHttpHandler
 	internal void LoadPageViewState()
 	{
 		object sState = LoadPageStateFromPersistenceMedium ();
-		if (sState != null)
-			LoadViewStateRecursive (sState);
-	}
-
-	protected virtual void SavePageStateToPersistenceMedium (object viewState)
-	{
-		_savedViewState = viewState;
-	}
-
-	private void SaveControlState (Control ctrl, Triplet savedData, XmlTextWriter writer)
-	{
-		writer.WriteStartElement ("control");
-		writer.WriteAttributeString ("id", ctrl.ID);
-		writer.WriteAttributeString ("type", ctrl.GetType ().ToString ());
-		StateBag state = savedData.First as StateBag;
-		if (state != null){
-			foreach (string key in state.Keys){
-				object o = state [key];
-				writer.WriteStartElement ("item");
-				writer.WriteAttributeString ("key", key);
-				if (o  == null)
-					o = "";
-				else if (o is string)
-					writer.WriteAttributeString ("value", o as string);
-				else
-					//FIXME: add more conversions to string for other types.
-					throw new NotSupportedException (o.GetType ().ToString ());
-
-				writer.WriteEndElement ();
-			}
-
-			ArrayList controlList = savedData.Second as ArrayList;
-			ArrayList stateList = savedData.Third as ArrayList;
-			int idx = 0;
-			foreach (Control child in controlList)
-				SaveControlState (child, stateList [idx++] as Triplet, writer);
+		if (sState != null) {
+			Pair pair = (Pair) sState;
+			LoadViewStateRecursive (pair.First);
+			_requiresPostBack = pair.Second as ArrayList;
 		}
-		writer.WriteEndElement ();
 	}
 
 	internal void SavePageViewState ()
 	{
-		//SavePageStateToPersistenceMedium (SaveViewStateRecursive ());
-		string outputFile = "page-" + this.ToString () + ".xml";
-		XmlTextWriter xmlWriter = new XmlTextWriter (outputFile, Encoding.UTF8);
-		xmlWriter.Formatting = Formatting.Indented;
-		xmlWriter.Indentation = 4;
-		xmlWriter.WriteStartDocument (true);
-		xmlWriter.WriteStartElement ("viewstate");
-		Triplet savedState = SaveViewStateRecursive () as Triplet;
-		SaveControlState (this, savedState, xmlWriter);
-		xmlWriter.WriteEndElement ();
-		xmlWriter.Close ();
+		Pair pair = new Pair ();
+		pair.First = SaveViewStateRecursive ();
+		pair.Second = _requiresPostBack;
+		SavePageStateToPersistenceMedium (pair);
 	}
 
 	public virtual void Validate ()

+ 7 - 6
mcs/class/System.Web/System.Web.UI/StateBag.cs

@@ -22,7 +22,7 @@ namespace System.Web.UI
 	{
 		private bool ignoreCase;
 		private bool marked;
-		private IDictionary bag;
+		private HybridDictionary bag;
 		
 		public StateBag (bool ignoreCase)
 		{
@@ -93,8 +93,9 @@ namespace System.Web.UI
 			else
 				val.Value = value;
 
-			if (val != null && marked)
+			if (val != null && marked) {
 				val.IsDirty = true;
+			}
 
 			return val;
 		}
@@ -153,8 +154,8 @@ namespace System.Web.UI
 			if(bag.Count > 0) {
 				ArrayList keyList = null, valList = null;
 
-				foreach(IDictionaryEnumerator current in bag) {
-					StateItem item = (StateItem)current.Value;
+				foreach (string key in bag.Keys) {
+					StateItem item = (StateItem) bag [key];
 
 					if (item.IsDirty) {
 						if (keyList == null) {
@@ -162,8 +163,8 @@ namespace System.Web.UI
 							valList = new ArrayList ();
 						}
 						
-						keyList.Add (current.Key);
-						valList.Add (current.Value);
+						keyList.Add (key);
+						valList.Add (item.Value);
 					}
 				}