2 // System.Web.UI.StateManagedCollection
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Sebastien Pouliot <sebastien@ximian.com>
7 // Marek Habersack (mhabersack@novell.com)
10 // Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Collections.Generic;
37 namespace System.Web.UI {
39 public abstract class StateManagedCollection : IList, IStateManager
41 ArrayList items = new ArrayList ();
42 bool saveEverything = false;
44 protected virtual object CreateKnownType (int index)
49 public void SetDirty ()
51 saveEverything = true;
52 for (int i = 0; i < items.Count; i++)
53 SetDirtyObject (items[i]);
56 protected abstract void SetDirtyObject (object o);
58 protected virtual Type [] GetKnownTypes ()
64 protected virtual void OnClear ()
68 protected virtual void OnClearComplete ()
72 protected virtual void OnInsert (int index, object value)
76 protected virtual void OnInsertComplete (int index, object value)
80 protected virtual void OnRemove (int index, object value)
84 protected virtual void OnRemoveComplete (int index, object value)
88 protected virtual void OnValidate (object value)
91 throw new ArgumentNullException ("value");
96 void IStateManager.LoadViewState (object savedState)
98 if (savedState == null) {
99 foreach (IStateManager i in items)
100 i.LoadViewState (null);
104 Triplet state = savedState as Triplet;
106 throw new InvalidOperationException ("Internal error.");
108 List <int> indices = state.First as List <int>;
109 List <object> states = state.Second as List <object>;
110 List <object> types = state.Third as List <object>;
111 IList list = this as IList;
115 saveEverything = indices == null;
116 if (saveEverything) {
119 for (int i = 0; i < states.Count; i++) {
122 item = (IStateManager) Activator.CreateInstance ((Type) t);
124 item = (IStateManager) CreateKnownType ((int) t);
128 item.TrackViewState ();
129 item.LoadViewState (states [i]);
136 for (int i = 0; i < indices.Count; i++) {
140 item = list [idx] as IStateManager;
141 item.TrackViewState ();
142 item.LoadViewState (states [i]);
149 item = (IStateManager) Activator.CreateInstance ((Type) t);
151 item = (IStateManager) CreateKnownType ((int) t);
155 item.TrackViewState ();
156 item.LoadViewState (states [i]);
161 void AddListItem <T> (ref List <T> list, T item)
164 list = new List <T> ();
169 object IStateManager.SaveViewState ()
171 Type[] knownTypes = GetKnownTypes ();
172 bool haveData = false, haveKnownTypes = knownTypes != null && knownTypes.Length > 0;
173 int count = items.Count;
178 List <int> indices = null;
179 List <object> states = null;
180 List <object> types = null;
182 for (int i = 0; i < count; i++) {
183 item = items [i] as IStateManager;
186 item.TrackViewState ();
187 itemState = item.SaveViewState ();
188 if (saveEverything || itemState != null) {
190 type = item.GetType ();
191 idx = haveKnownTypes ? Array.IndexOf (knownTypes, type) : -1;
194 AddListItem <int> (ref indices, i);
195 AddListItem <object> (ref states, itemState);
197 AddListItem <object> (ref types, type);
199 AddListItem <object> (ref types, idx);
206 return new Triplet (indices, states, types);
209 void IStateManager.TrackViewState ()
211 isTrackingViewState = true;
212 if (items != null && items.Count > 0) {
214 foreach (object o in items) {
215 item = o as IStateManager;
218 item.TrackViewState ();
223 bool isTrackingViewState;
224 bool IStateManager.IsTrackingViewState {
225 get { return isTrackingViewState; }
229 #region ICollection, IList, IEnumerable
235 this.OnClearComplete ();
237 if (isTrackingViewState)
241 public IEnumerator GetEnumerator ()
243 return items.GetEnumerator ();
246 public void CopyTo (Array array, int index)
248 items.CopyTo (array, index);
251 IEnumerator IEnumerable.GetEnumerator ()
253 return GetEnumerator ();
256 int IList.Add (object value)
259 if (isTrackingViewState) {
260 ((IStateManager) value).TrackViewState ();
261 SetDirtyObject (value);
264 OnInsert (-1, value);
266 OnInsertComplete (-1, value);
271 void IList.Insert (int index, object value)
274 if (isTrackingViewState) {
275 ((IStateManager) value).TrackViewState ();
279 OnInsert (index, value);
280 items.Insert (index, value);
281 OnInsertComplete(index, value);
284 void IList.Remove (object value)
289 IList list = (IList)this;
290 int i = list.IndexOf (value);
295 void IList.RemoveAt (int index)
297 object o = items [index];
300 items.RemoveAt (index);
301 OnRemoveComplete(index, o);
303 if (isTrackingViewState)
312 bool IList.Contains (object value)
318 return items.Contains (value);
321 int IList.IndexOf (object value)
327 return items.IndexOf (value);
331 get { return items.Count; }
334 int ICollection.Count {
335 get { return items.Count; }
338 bool ICollection.IsSynchronized {
339 get { return false; }
342 object ICollection.SyncRoot {
346 bool IList.IsFixedSize {
347 get { return false; }
350 bool IList.IsReadOnly {
351 get { return false; }
354 object IList.this [int index] {
355 get { return items [index]; }
357 if (index < 0 || index >= Count)
358 throw new ArgumentOutOfRangeException ("index");
361 if (isTrackingViewState) {
362 ((IStateManager) value).TrackViewState ();
366 items [index] = value;