Click here to Skip to main content
15,896,912 members
Articles / Programming Languages / C#

EasiReports

Rate me:
Please Sign up or sign in to vote.
4.87/5 (64 votes)
13 Feb 2006CPOL6 min read 482.6K   9.7K   219  
A library to add reports to your application.
using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Diagnostics;

//using BindableEditableObject;
using EasiReports.Metadata;

namespace SortedViewNamespace
{
	public class SortedView : IBindingList
	{
		private IList mList = null;
		private bool mSupportsBinding = false;
		private IBindingList mBindingList = null;
		private bool mSorted = false;
		private PropertyDescriptor mSortBy = null;
		private ListSortDirection mSortOrder = ListSortDirection.Ascending;
		private ArrayList mSortIndex = new ArrayList();
		private object AddNewObject = null;

		public IList List
		{
			get
			{
				return mList;
			}
		}

		public SortedView( IList list )
		{
			mList = list;

			if ( mList is IBindingList )
			{
				mSupportsBinding = true;
				mBindingList = (IBindingList) mList;
				mBindingList.ListChanged += new ListChangedEventHandler( SourceChanged );
			}

			if ( ItemIsBindableEditableObject )
			{
				foreach ( IBindableEditableObject o in mList )
					o.EditCalled += new EditCalledEventHandler( EditCalled );
			}
		}

		private void EditCalled( object sender, EditCalledEventArgs e )
		{
			switch ( e.EditCalledType )
			{
			case EditCalledType.BeginEdit :
				Debug.WriteLine( "*BeginEdit*" ); 
				break;

			case EditCalledType.CancelEdit :
				Debug.WriteLine( "*CancelEdit*" );
				if ( sender == AddNewObject )
				{
					( (IList) this ).Remove( AddNewObject );
					AddNewObject = null;
				}

				break;

			case EditCalledType.EndEdit :
				Debug.WriteLine( "*EndEdit*" );
				if ( AddNewObject == null || sender == AddNewObject )
				{
					if ( mSorted ) DoSort();
					else
					{
						int index = ( (IList) this ).IndexOf( sender );
						if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemChanged, index ) );
					}

					AddNewObject = null;
				}
				break;
			}
		}

		private void SourceChanged( object sender, ListChangedEventArgs e )
		{
			if ( mSorted )
			{
				if ( e.ListChangedType == ListChangedType.ItemAdded )
				{
					object oNew = mList[ e.NewIndex ];
					ListItem item = new ListItem( mSortBy.GetValue( oNew ), oNew );

					if ( mSortOrder == ListSortDirection.Ascending )
					{
						mSortIndex.Add( item );
					}
					else
					{
						mSortIndex.Insert( 0, item );
					}

					if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, mSortIndex.Count - 1 ) );
				}
				else
					DoSort();
			}
			else
				if ( ListChanged != null ) ListChanged( this, e );
		}

//-----------------------------------------------------------------------------
// Sort/Unsort

		private void DoSort()
		{
			mSortIndex.Clear();

			if ( mSortBy == null )
			{
				foreach ( object o in mList )
					mSortIndex.Add( new ListItem( o, o ) );
			}
			else
			{
				foreach ( object o in mList )
					mSortIndex.Add( new ListItem( mSortBy.GetValue( o ), o ) );
			}

			mSortIndex.Sort();
			mSorted = true;

			if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.Reset, 0 ) );
		}

		private void UndoSort()
		{
			mSortIndex.Clear();
			mSortBy = null;
			mSortOrder = ListSortDirection.Ascending;
			mSorted = false;

			if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.Reset, 0 ) );
		}

//-----------------------------------------------------------------------------
// IList

		IEnumerator IEnumerable.GetEnumerator()
		{
			if ( mSorted ) return new SortedEnumerator( mSortIndex, mSortOrder );

			return mList.GetEnumerator();
		}

		void ICollection.CopyTo( Array array, int index )
		{
			mList.CopyTo( array, index );
		}

		int ICollection.Count
		{
			get
			{
				return mList.Count;
			}
		}

		bool ICollection.IsSynchronized
		{
			get
			{
				return mList.IsSynchronized;
			}
		}

		object ICollection.SyncRoot
		{
			get
			{
				return mList.SyncRoot;
			}
		}

		int IList.Add( object value )
		{
			return mList.Add( value );
		}

		void IList.Clear()
		{
			mList.Clear();
		}

		bool IList.Contains( object value )
		{
			return mList.Contains( value );
		}

		int IList.IndexOf( object value )
		{
			if ( mSorted )
			{
				int index = 0;

				foreach ( ListItem item in mSortIndex )
				{
					if ( item.Item.Equals( value ) )
						return index;

					index++;
				}

				return -1;
			}
			else
				return mList.IndexOf( value );
		}

		void IList.Insert( int index, object value )
		{
			mList.Insert( index, value );
		}

		bool IList.IsFixedSize
		{
			get
			{
				return mList.IsFixedSize;
			}
		}

		bool IList.IsReadOnly
		{
			get
			{
//				return true;
				return mList.IsReadOnly;
			}
		}

		object IList.this[ int index ]
		{
			get
			{
Debug.Assert( index < mList.Count );
				if ( mSorted ) return GetSortedItem( index );
				return mList[ index ];
			}

			set
			{
Debug.Assert( index < mList.Count );
				if ( mSorted )
				{
					int pos = mList.IndexOf( GetSortedItem( index ) );
					mList[ pos ] = value;

					if ( ! mSupportsBinding ) DoSort();
				}
				else
					mList[ index ] = value;
			}
		}

		private object GetSortedItem( int index )
		{
			if ( mSortOrder == ListSortDirection.Ascending )
				return ( (ListItem) mSortIndex[ index ] ).Item;
			else
				return ( (ListItem) mSortIndex[ mSortIndex.Count - 1 - index ] ).Item;
		}

		void IList.Remove( object value )
		{
			IBindableEditableObject beo = value as IBindableEditableObject;
			if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );

			mList.Remove( value );

			if ( ! mSupportsBinding )
			{
				int index = mList.IndexOf( value );
				SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, index ) );
			}
		}

		void IList.RemoveAt( int index )
		{
			if ( mSorted )
			{
				object o = GetSortedItem( index );

				IBindableEditableObject beo = o as IBindableEditableObject;
				if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );

				int pos = mList.IndexOf( o );
				mList.RemoveAt( pos );
				if ( ! mSupportsBinding )
					SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, pos ) );
			}
			else
			{
				object o = mList[ index ];

				IBindableEditableObject beo = o as IBindableEditableObject;
				if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );

				mList.RemoveAt( index );
				if ( ! mSupportsBinding )
					SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, index ) );
			}
		}

//-----------------------------------------------------------------------------
// IBindingList

		void IBindingList.AddIndex( PropertyDescriptor property )
		{
			if ( mSupportsBinding )
				mBindingList.AddIndex( property );
			else
				throw new NotSupportedException();
		}

		int x = 1;
		object IBindingList.AddNew()
		{
			Debug.WriteLine( "AddNew" + x++ );

			if ( mSupportsBinding )
				return mBindingList.AddNew();

			Type t = ItemType;
			AddNewObject = Activator.CreateInstance( t );

			IBindableEditableObject beo = AddNewObject as IBindableEditableObject;
			if ( beo != null ) beo.EditCalled += new EditCalledEventHandler( EditCalled );

			int iNewObject = mList.Add( AddNewObject );
//			if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, mList.Count - 1 ) );

			if ( ! mSupportsBinding )
			SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, iNewObject ) );

			return AddNewObject;
		}

		bool IBindingList.AllowEdit
		{
			get
			{
				if ( mSupportsBinding )
					return mBindingList.AllowEdit;

//				return false;
				return true;
			}
		}

		bool IBindingList.AllowNew
		{
			get
			{
				if ( mSupportsBinding )
					return mBindingList.AllowNew;

//				return false;
				return ItemIsBindableEditableObject;
			}
		}

		bool IBindingList.AllowRemove
		{
			get
			{
				if ( mSupportsBinding )
					return mBindingList.AllowRemove;

//				return false;
				return true;
			}
		}

		public bool ItemIsBindableEditableObject
		{
			get
			{
				return ItemType.GetInterface( "IBindableEditableObject" ) != null;
			}
		}

		public Type ItemType
		{
			get
			{
				Type t = ( (object) mList ).GetType();
				MemberInfo[] defs = t.GetDefaultMembers();

				foreach ( MemberInfo member in defs )
				{
					if ( member.MemberType == MemberTypes.Property )
					{
						Type itemType = ( (PropertyInfo) member ).GetGetMethod().ReturnType;
						return itemType;
					}
				}

				if ( mList.Count > 0 )
				{
					Type itemType = mList[ 0 ].GetType();
					return itemType;
				}

				throw new Exception( "Cannot determine collection item type" );
			}
		}

		public void ApplySort( string property, ListSortDirection direction )
		{
			if ( property.Length > 0 )
			{
				Type itemType = ItemType;

				PropertyDescriptorCollection props = TypeDescriptor.GetProperties( itemType );

				foreach ( PropertyDescriptor prop in props )
				{
					if ( prop.Name == property )
					{
						mSortBy = prop;
						break;
					}
				}
			}

			( (IBindingList) this ).ApplySort( mSortBy, direction );
		}

		void IBindingList.ApplySort( PropertyDescriptor property, ListSortDirection direction )
		{
			mSortBy = property;
			mSortOrder = direction;
			DoSort();
		}

		int IBindingList.Find( PropertyDescriptor property, object key )
		{
			if ( mSupportsBinding )
				return mBindingList.Find( property, key );

			throw new NotSupportedException();
		}

		bool IBindingList.IsSorted
		{
			get
			{
				return mSorted;
			}
		}

		public event ListChangedEventHandler ListChanged;

		void IBindingList.RemoveIndex( PropertyDescriptor property )
		{
			if ( mSupportsBinding )
				mBindingList.RemoveIndex( property );
			else
				throw new NotSupportedException();
		}

		void IBindingList.RemoveSort()
		{
			UndoSort();
		}

		ListSortDirection IBindingList.SortDirection
		{
			get
			{
				return mSortOrder;
			}
		}

		PropertyDescriptor IBindingList.SortProperty
		{
			get
			{
				return mSortBy;
			}
		}

		bool IBindingList.SupportsChangeNotification
		{
			get
			{
				return true;
			}
		}

		bool IBindingList.SupportsSearching
		{
			get
			{
				if ( mSupportsBinding )
					return mBindingList.SupportsSearching;

				return false;
			}
		}

		bool IBindingList.SupportsSorting
		{
			get
			{
				return true;
			}
		}

//-----------------------------------------------------------------------------

		private class ListItem : IComparable
		{
			public object Key;
			public object Item;

			public ListItem( object key, object item )
			{
				this.Key = key;
				this.Item = item;
			}

			int IComparable.CompareTo( object o )
			{
				object target = ( (ListItem) o ).Key;

				if ( Key is IComparable ) return ( (IComparable) Key ).CompareTo( target );
				
				if ( Key.Equals( target ) ) return 0;

				return Key.ToString().CompareTo( target.ToString() );
			}

			public override string ToString()
			{
				return Key.ToString ();
			}
		}

//-----------------------------------------------------------------------------

		private class SortedEnumerator : IEnumerator
		{
			private ArrayList mSortIndex;
			private ListSortDirection mSortOrder;
			private int index;

			public SortedEnumerator( ArrayList SortIndex, ListSortDirection Direction )
			{
				mSortIndex = SortIndex;
				mSortOrder = Direction;
				( (IEnumerator) this ).Reset();
			}

			void IEnumerator.Reset()
			{
				if ( mSortOrder == ListSortDirection.Ascending )
					index = -1;
				else index = mSortIndex.Count;
			}

			bool IEnumerator.MoveNext()
			{
				if ( mSortOrder == ListSortDirection.Ascending )
				{
					if ( index < mSortIndex.Count - 1 )
					{
						index++;
						return true;
					}
					
					return false;
				}

				if ( index > 0 )
				{
					index--;
					return true;
				}

				return false;
			}

			object IEnumerator.Current
			{
				get
				{
					return ( (ListItem) mSortIndex[ index ] ).Item;
				}
			}
		}

//-----------------------------------------------------------------------------

	}
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
I discovered C# and .NET 1.0 Beta 1 in late 2000 and loved them immediately.
I have been writing software professionally in C# ever since

In real life, I have spent 3 years travelling abroad,
I have held a UK Private Pilots Licence for 20 years,
and I am a PADI Divemaster.

I now live near idyllic Bournemouth in England.

I can work 'virtually' anywhere!

Comments and Discussions