Click here to Skip to main content
15,884,537 members
Articles / Web Development / ASP.NET

Developing Next Generation Smart Clients using .NET 2.0 working with Existing .NET 1.1 SOA-based XML Web Services

Rate me:
Please Sign up or sign in to vote.
4.96/5 (134 votes)
16 Aug 200540 min read 1.2M   3.9K   462  
Comprehensive guide to development of .NET 2.0 Smart Clients working with existing Service Oriented Architecture based XML web services, fully utilizing the Enterprise Library
using System;
using System.Xml.Serialization;
using System.Collections;
using System.Runtime.Serialization;

namespace SmartInstitute.ObjectModel
{
	public delegate void CollectionAddHandler( CollectionBase collection, ItemBase item );

	public delegate void CollectionRemoveHandler( CollectionBase collection, ItemBase item );

	public delegate void CollectionClearHandler( CollectionBase collection );

	public delegate void CollectionAddRangeHandler(CollectionBase collection);

	public delegate void CollectionRefreshHandler( CollectionBase collection );


	/// <summary>
	/// Base class for all collection type classes
	/// </summary>
	[Serializable]
	public abstract class CollectionBase : System.Collections.CollectionBase
	{
		public event ItemChangeHandler OnItemChange;
		public event ItemDetachHandler OnItemDetach;
		public event ItemShowHandler OnItemShow;
		public event ItemSelectHandler OnItemSelect;
		public event ItemUndoStateHandler OnItemUndo;
		public event ItemRedoStateHandler OnItemRedo;
		public event ItemBeginUpdateHandler OnItemBeginUpdate;
		public event ItemEndUpdateHandler OnItemEndUpdate;

		public event CollectionAddHandler OnItemCollectionAdd;
		public event CollectionRemoveHandler OnItemCollectionRemove;
		public event CollectionClearHandler OnItemCollectionClear;
		public event SelectionChangeHandler OnItemCollectionSelectionChanged;
		public event CollectionAddRangeHandler OnAddRange;
		public event CollectionRefreshHandler OnRefresh;

		private bool _IsDirty = false;

		/// <summary>
		/// The parent reference must be ignored in serialization because
		/// it creates circular reference and XmlSerializer cannot serialize it.
		/// </summary>
		[XmlIgnore]
		[NonSerialized]
		private WeakReference _Parent;

		[XmlIgnore]
		public object Parent
		{
			get
			{
				if( _Parent.IsAlive )
				{
					return _Parent.Target;
				}
				else
				{
					return null;
				}
			}
			set
			{
				_Parent = new WeakReference( value );
			}
		}

		public bool IsDirty
		{
			get
			{
				return _IsDirty;
			}
			set
			{
				_IsDirty = value;
			}
		}

		protected CollectionBase( object parent )
		{
			this.Parent = parent;
		}

		protected virtual void AddRange(Array items)
		{
			foreach (ItemBase item in items)
			{
				this.Add(item);
			}

			if (null != OnAddRange)
				OnAddRange(this);
		}

		/// <summary>
		/// Add new item to the collection
		/// </summary>
		/// <param name="item"></param>
		protected virtual int Add( ItemBase item )
		{
			// Attach to events in order to listen to events for individual item
			// events are propagated to the parent
			this.ListenChildItem( item );
			
			if( null == item.Parent )
				item.Parent = this;

			this.IsDirty = true;
			int result = List.Add( item );

			if( null != OnItemCollectionAdd )
			{
				OnItemCollectionAdd( this, item );
			}

			return result;
		}

		protected virtual void Remove( ItemBase item )
		{
			if( List.Contains( item ) )
			{
				this.IsDirty = true;

				List.Remove( item );

				if( null != OnItemCollectionRemove )
				{
					OnItemCollectionRemove( this, item );
				}
			}
		}

		new public void RemoveAt(int index)
		{
			ItemBase item = this[index];
			this.Remove(item);
		}

		new public void Clear( )
		{	
			// remove from last
			while( List.Count > 0 )
			{
				this.IsDirty = true;

				ItemBase item = this[ List.Count - 1 ];
				this.Remove( item );
			}

			if( null != OnItemCollectionClear )
			{
				OnItemCollectionClear( this );
			}

		}

		protected ItemBase this[ int index ]
		{
			get
			{
				return (ItemBase) List[ index ];
			}
			set
			{
				List[ index ] = value;
			}
		}

		/// <summary>
		/// Copy all items from this instance of collection to the specified instance		
		/// </summary>
		/// <param name="col"></param>
		/// <param name="index"></param>
		public void CopyTo( CollectionBase col, int index )
		{
			foreach (ItemBase item in base.InnerList)
			{
				col.Add(item);
			}
		}

		public void Refresh()
		{
			if (null != OnRefresh)
				OnRefresh( this );
		}

		#region Child Item event handling

		private void item_OnShow( ItemBase item )
		{
			if( null != OnItemShow )
			{
				OnItemShow( item );
			}
		}

		/// <summary>
		/// Propagate item change event
		/// </summary>
		/// <param name="item"></param>
		private void item_OnChange( ItemBase item, string changeType )
		{
			if( null != OnItemChange )
			{
				OnItemChange( item, changeType );
			}
		}

		/// <summary>
		/// Propagate item detach event
		/// </summary>
		/// <param name="item"></param>
		private void item_OnDetach( ItemBase item )
		{
			// TODO: need to remove event listener
			if( null != OnItemDetach )
			{
				OnItemDetach( item );
			}
		}

		
		// ----------------------- Child Item event handling --------------------

		protected void ListenChildItem( ItemBase item )
		{
			item.OnChange += new ItemChangeHandler( item_OnChange );
			item.OnDetach += new ItemDetachHandler( item_OnDetach );
			item.OnSelect += new ItemSelectHandler(item_OnSelect);
			item.OnShow += new ItemShowHandler( item_OnShow );

			item.OnBeginUpdate += new ItemBeginUpdateHandler(item_OnBeginUpdate);
			item.OnEndUpdate += new ItemEndUpdateHandler(item_OnEndUpdate);
			item.OnUndoState += new ItemUndoStateHandler(item_OnUndoState);
			item.OnRedoState += new ItemRedoStateHandler(item_OnRedoState);

			item.OnCollectionAdd += new CollectionAddHandler(item_OnCollectionAdd);
			item.OnCollectionClear += new CollectionClearHandler(item_OnCollectionClear);
			item.OnCollectionRemove += new CollectionRemoveHandler(item_OnCollectionRemove);
			item.OnSelectionChanged += new SelectionChangeHandler(item_OnSelectionChanged);
		}

		#endregion

		#region Event Handlers 

		private void item_OnSelect(ItemBase item)
		{
			if( null != OnItemSelect )
				OnItemSelect( item );
		}

		private void item_OnCollectionAdd(CollectionBase collection, ItemBase item)
		{
			if( null != OnItemCollectionAdd )			
				OnItemCollectionAdd( collection, item );
		}

		private void item_OnCollectionClear(CollectionBase collection)
		{
			if( null != OnItemCollectionClear )
				OnItemCollectionClear( collection );
		}

		private void item_OnCollectionRemove(CollectionBase collection, ItemBase item)
		{
			if( null != OnItemCollectionRemove )
				OnItemCollectionRemove( collection, item );
		}

		private void item_OnSelectionChanged(CollectionBase collection, ItemBase item)
		{
			if( null != OnItemCollectionSelectionChanged )
				OnItemCollectionSelectionChanged( collection, item );
		}

		private void item_OnBeginUpdate(ItemBase item, string name)
		{
			if( null != OnItemBeginUpdate )
				OnItemBeginUpdate( item, name );
		}

		private void item_OnUndoState(ItemBase item)
		{
			if( null != OnItemUndo )
				OnItemUndo( item );
		}

		private void item_OnRedoState(ItemBase item)
		{
			if( null != OnItemRedo )
				OnItemRedo( item );
		}

		private void item_OnEndUpdate(ItemBase item)
		{
			if( null != OnItemEndUpdate )
				OnItemEndUpdate( item );
		}

		#endregion

	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom

Comments and Discussions