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

Zeta Enterprise Library

Rate me:
Please Sign up or sign in to vote.
4.97/5 (14 votes)
16 Jan 2010CPOL3 min read 50.4K   2.3K   48  
A small set of general-purpose classes for using in .NET applications (2.0 or higher)
namespace Zeta.EnterpriseLibrary.Windows.Controls
{
	#region Using directives.
	// ----------------------------------------------------------------------

	using System.Windows.Forms;
	using System.Diagnostics;
	using System.ComponentModel;
	using System.Collections;

	// ----------------------------------------------------------------------
	#endregion

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// An extended list view control that has tri-state check boxes.
	/// </summary>
	public partial class TriStateCheckBoxesListView :
		ListView
	{
		#region Public tri-state related methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// Constructor.
		/// </summary>
		public TriStateCheckBoxesListView()
		{
			InitializeComponent();
		}

		// ------------------------------------------------------------------
		#endregion

		#region Public tri-state related properties.
		// ------------------------------------------------------------------

		/// <summary>
		/// Gets or sets whether to have checkboxes beside the items and
		/// whether they have tri state.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if [use tri state check boxes]; otherwise, <c>false</c>.
		/// </value>
		[Category( @"Appearance" ),
		Description( @"Indicates whether tri-state check boxes are displayed beside list view items." )]
		public bool UseTriStateCheckBoxes
		{
			get
			{
				return StateImageList == CheckedTriStateImageList;
			}
			set
			{
				// Only if changed.
				if ( UseTriStateCheckBoxes != value )
				{
					if ( value )
					{
						CheckBoxes = false;
						StateImageList = CheckedTriStateImageList;

						foreach ( ListViewItem item in Items )
						{
							DoApplyStateImageIndexToItem(
								item,
								TriStateUncheckedStateImageIndex, false );
						}
					}
					else
					{
						StateImageList = null;

						foreach ( ListViewItem item in Items )
						{
							DoApplyStateImageIndexToItem(
								item,
								TriStateNoStateImageIndex,
								false );
						}
					}
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether check boxes are displayed
		/// next to the list view items in the list view control.
		/// </summary>
		/// <value></value>
		/// <remarks>
		/// Provide new version of this property to ensure only one of the
		/// tri-state and normal checkboxes are shown.
		/// </remarks>
		public new bool CheckBoxes
		{
			get
			{
				return base.CheckBoxes;
			}
			set
			{
				if ( value != CheckBoxes )
				{
					UseTriStateCheckBoxes = false;
					base.CheckBoxes = value;
				}
			}
		}

		/// <summary>
		/// Gets and sets whether all selected list view items are
		/// automatically updated when one selected list view item is
		/// checked/unchecked by the user.
		/// </summary>
		/// <value><c>true</c> if [auto check selected]; otherwise, <c>false</c>.</value>
		[Category( @"Behavior" ),
		Description( @"Gets and sets whether all selected list view items are automatically updated when one selected list view item is checked/unchecked by the user." )]
		public bool AutoCheckSelected
		{
			get
			{
				return autoCheckSelected;
			}
			set
			{
				autoCheckSelected = value;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Public tri-state related enums.
		// ------------------------------------------------------------------

		/// <summary>
		/// Apply more complex/recursive checks to a list view item.
		/// </summary>
		public enum ItemsCheckState
		{
			#region Enum members.

			/// <summary>
			/// Check all items.
			/// </summary>
			CheckAllItems,

			/// <summary>
			/// Uncheck all items.
			/// </summary>
			UncheckAllItems,

			/// <summary>
			/// Set all items to indeterminate.
			/// </summary>
			IndeterminateAllItems,

			/// <summary>
			/// Check all selected items.
			/// </summary>
			CheckAllSelectedItems,

			/// <summary>
			/// Uncheck all selected items.
			/// </summary>
			UncheckAllSelectedItems,

			/// <summary>
			/// Set all selected items to indeterminate.
			/// </summary>
			IndeterminateAllSelectedItems,

			#endregion
		}

		/// <summary>
		/// How the check state was set.
		/// </summary>
		public enum ListViewAction
		{
			#region Enum members.

			/// <summary>
			/// Unknown or by code.
			/// </summary>
			Unknown,

			/// <summary>
			/// By the keyboard.
			/// </summary>
			ByKeyboard,

			/// <summary>
			/// By the mouse.
			/// </summary>
			ByMouse

			#endregion
		}

		// ------------------------------------------------------------------
		#endregion

		#region Public tri-state related methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// Applies a new check state to the given list view item.
		/// The UseTriStateCheckBoxes property must be set to TRUE.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="checkState">State of the check.</param>
		public void SetItemCheckState(
			ListViewItem item,
			CheckState checkState )
		{
			Debug.Assert(
				UseTriStateCheckBoxes,
				@"The ExtendedListViewControl.UseTriStateCheckBoxes property must be set to TRUE before setting the item check state." );

			// Use ListViewAction.Unknown here, to indicate 
			// that it was called from outside.
			DoSetItemCheckState(
				item,
				ListViewAction.Unknown,
				checkState );
		}

		/// <summary>
		/// Get the check state of a given list view item.
		/// The UseTriStateCheckBoxes property must be set to TRUE.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <returns></returns>
		public CheckState GetItemCheckState(
			ListViewItem item )
		{
			Debug.Assert(
				UseTriStateCheckBoxes,
				@"The ExtendedListViewControl.UseTriStateCheckBoxes property must be set to TRUE before setting the item check state." );

			return ConvertStateImageIndexToCheckState( item.StateImageIndex );
		}

		/// <summary>
		/// Apply more complex/recursive checks to a list view item.
		/// </summary>
		/// <param name="newStates">The new states.</param>
		public void ChangeItemsCheckStates(
			ItemsCheckState newStates )
		{
			switch ( newStates )
			{
				case ItemsCheckState.CheckAllItems:
					DeepSetCheckState(
						CheckState.Checked,
						Items );
					break;
				case ItemsCheckState.UncheckAllItems:
					DeepSetCheckState(
						CheckState.Unchecked,
						Items );
					break;
				case ItemsCheckState.IndeterminateAllItems:
					DeepSetCheckState(
						CheckState.Indeterminate,
						Items );
					break;
				case ItemsCheckState.CheckAllSelectedItems:
					DeepSetCheckState(
						CheckState.Checked,
						SelectedItems );
					break;
				case ItemsCheckState.UncheckAllSelectedItems:
					DeepSetCheckState(
						CheckState.Unchecked,
						SelectedItems );
					break;
				case ItemsCheckState.IndeterminateAllSelectedItems:
					DeepSetCheckState(
						CheckState.Indeterminate,
						SelectedItems );
					break;

				default:
					Debug.Assert(
						false,
						string.Format(
						@"Unknown ItemsCheckState enum value '{0}'.",
						newStates ) );
					break;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Events handler.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		public delegate void ItemCheckTriStateEventHandler(
			object sender,
			ItemCheckTriStateEventArgs args );

		/// <summary>
		/// 
		/// </summary>
		public delegate void ItemCheckedTriStateEventHandler(
			object sender,
			ItemCheckedTriStateEventArgs args );

		// ------------------------------------------------------------------
		#endregion

		#region Event arguments.
		// ------------------------------------------------------------------

		/// <summary>
		/// Specialized arguments class.
		/// </summary>
		public class ItemCheckTriStateEventArgs :
			ItemCheckEventArgs
		{
			/// <summary>
			/// Constructor.
			/// </summary>
			/// <param name="item">The item.</param>
			/// <param name="action">The action.</param>
			/// <param name="newCheckValue">The new check value.</param>
			/// <param name="currentCheckValue">The current check value.</param>
			public ItemCheckTriStateEventArgs(
				ListViewItem item,
				ListViewAction action,
				CheckState newCheckValue,
				CheckState currentCheckValue )
				:
				base( item.Index, newCheckValue, currentCheckValue )
			{
				this.item = item;
				this.action = action;
			}

			/// <summary>
			/// Gets the action.
			/// </summary>
			/// <value>The action.</value>
			public ListViewAction Action
			{
				get
				{
					return action;
				}
			}

			/// <summary>
			/// Gets or sets a value indicating whether this <see cref="ItemCheckTriStateEventArgs"/> is cancel.
			/// </summary>
			/// <value><c>true</c> if cancel; otherwise, <c>false</c>.</value>
			public bool Cancel
			{
				get
				{
					return cancel;
				}
				set
				{
					cancel = value;
				}
			}

			/// <summary>
			/// Gets the item.
			/// </summary>
			/// <value>The item.</value>
			public ListViewItem Item
			{
				get
				{
					return item;
				}
			}

			/// <summary>
			/// The state image index of the related item.
			/// </summary>
			/// <value>The index of the current state image.</value>
			public int CurrentStateImageIndex
			{
				get
				{
					return ConvertCheckStateToImageIndex(
						CurrentValue );
				}
			}

			/// <summary>
			/// The state image index about to set to the related item.
			/// </summary>
			/// <value>The new index of the state image.</value>
			public int NewStateImageIndex
			{
				get
				{
					return ConvertCheckStateToImageIndex(
						NewValue );
				}
			}

			/// <summary>
			/// 
			/// </summary>
			private readonly ListViewItem item = null;
			private bool cancel = false;
			private readonly ListViewAction action;
		}

		/// <summary>
		/// Specialized arguments class.
		/// </summary>
		public class ItemCheckedTriStateEventArgs :
			ItemCheckedEventArgs
		{
			/// <summary>
			/// Initializes a new instance of the <see cref="ItemCheckedTriStateEventArgs"/> class.
			/// </summary>
			/// <param name="item">The item.</param>
			/// <param name="action">The action.</param>
			/// <param name="stateImageIndex">Index of the state image.</param>
			public ItemCheckedTriStateEventArgs(
				ListViewItem item,
				ListViewAction action,
				int stateImageIndex )
				:
				base( item )
			{
				this.action = action;
				this.stateImageIndex = stateImageIndex;
			}

			/// <summary>
			/// Gets the action.
			/// </summary>
			/// <value>The action.</value>
			public ListViewAction Action
			{
				get
				{
					return action;
				}
			}

			/// <summary>
			/// The state image index of the related item.
			/// </summary>
			/// <value>The index of the state image.</value>
			public int StateImageIndex
			{
				get
				{
					return stateImageIndex;
				}
			}

			/// <summary>
			/// The check state of the related item.
			/// </summary>
			/// <value>The state of the check.</value>
			public CheckState CheckState
			{
				get
				{
					return ConvertStateImageIndexToCheckState(
						stateImageIndex );
				}
			}

			/// <summary>
			/// 
			/// </summary>
			private readonly int stateImageIndex;
			private readonly ListViewAction action;
		}

		// ------------------------------------------------------------------
		#endregion

		#region Events.
		// ------------------------------------------------------------------

		/// <summary>
		/// Event that occurs when a check box on a list view item is about to be checked or unchecked.
		/// </summary>
		[Category( @"Behavior" ),
		Description( @"Occurs when a check box on a list view item is about to be checked or unchecked." )]
		public event ItemCheckTriStateEventHandler ItemCheckTriState;

		/// <summary>
		/// Event that occurs when a check box on a list view item has been checked or unchecked.
		/// </summary>
		[Category( @"Behavior" ),
		Description( @"Occurs when a check box on a list view item has been checked or unchecked." )]
		public event ItemCheckedTriStateEventHandler ItemCheckedTriState;

		// ------------------------------------------------------------------
		#endregion

		#region Private methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// If configured, some auto-steps could be performed after a check.
		/// </summary>
		/// <param name="args">The ItemCheckedTriStateEventArgs 
		/// instance containing the event data.</param>
		private void CheckPerformAutoStepsTriStateChecked(
			ItemCheckedTriStateEventArgs args )
		{
			if ( args.Action == ListViewAction.ByKeyboard ||
				args.Action == ListViewAction.ByMouse )
			{
				if ( AutoCheckSelected )
				{
					if ( args.CheckState == CheckState.Checked )
					{
						ChangeItemsCheckStates(
							ItemsCheckState.CheckAllSelectedItems );
					}
					else if ( args.CheckState == CheckState.Unchecked )
					{
						ChangeItemsCheckStates(
							ItemsCheckState.UncheckAllSelectedItems );
					}
				}
			}
		}

		/// <summary>
		/// Call this internally.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="checkState">State of the check.</param>
		private void InternalSetItemCheckState(
			ListViewItem item,
			CheckState checkState )
		{
			DoSetItemCheckState(
				item,
				ListViewAction.Unknown,
				checkState );
		}

		/// <summary>
		/// Applies a new check state to the given list view item.
		/// The UseTriStateCheckBoxes property must be set to TRUE.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="action">The action.</param>
		/// <param name="checkState">State of the check.</param>
		private void DoSetItemCheckState(
			ListViewItem item,
			ListViewAction action,
			CheckState checkState )
		{
			// Use ListViewAction.ByKeyboard here, 
			// to indicate that it was called from outside.
			SetTriStateToItem(
				item,
				action,
				ConvertCheckStateToImageIndex( checkState ),
				true );
		}

		/// <summary>
		/// Deeps the state of the set check.
		/// </summary>
		/// <param name="checkState">State of the check.</param>
		/// <param name="items">The items.</param>
		private void DeepSetCheckState(
			CheckState checkState,
			IList items )
		{
			foreach ( ListViewItem cn in items )
			{
				InternalSetItemCheckState( cn, checkState );
			}
		}

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.MouseClick"></see> event.
		/// </summary>
		/// <param name="e">An <see cref="T:System.Windows.Forms.MouseEventArgs"></see> that contains the event data.</param>
		protected override void OnMouseClick(
			MouseEventArgs e )
		{
			base.OnMouseClick( e );

			if ( UseTriStateCheckBoxes )
			{
				if ( e.Button == MouseButtons.Left )
				{
					ListViewHitTestInfo htInfo = HitTest( e.Location );

					if ( htInfo.Location == 
						ListViewHitTestLocations.StateImage )
					{
						ToggleTriStateCheck( 
							htInfo.Item, 
							ListViewAction.ByMouse );
					}
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.KeyDown"></see> event.
		/// </summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.KeyEventArgs"></see> that contains the event data.</param>
		protected override void OnKeyDown(
			KeyEventArgs e )
		{
			base.OnKeyDown( e );

			if ( UseTriStateCheckBoxes )
			{
				if ( e.KeyCode == Keys.Space )
				{
					ToggleTriStateCheck(
						FocusedItem,
						ListViewAction.ByKeyboard );
				}
			}
		}

		/// <summary>
		/// Toggles the tri state check.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="action">The action.</param>
		private void ToggleTriStateCheck(
			ListViewItem item,
			ListViewAction action )
		{
			if ( item.StateImageIndex == TriStateUncheckedStateImageIndex )
			{
				SetTriStateToItem(
					item,
					action,
					TriStateCheckedStateImageIndex,
					true );
			}
			else
			{
				SetTriStateToItem(
					item,
					action,
					TriStateUncheckedStateImageIndex,
					true );
			}
		}

		/// <summary>
		/// Map a state image index to a check state.
		/// </summary>
		/// <param name="imageIndex">Index of the image.</param>
		/// <returns></returns>
		private static CheckState ConvertStateImageIndexToCheckState(
			int imageIndex )
		{
			if ( imageIndex == TriStateCheckedStateImageIndex )
			{
				return CheckState.Checked;
			}
			else if ( imageIndex == TriStateUncheckedStateImageIndex )
			{
				return CheckState.Unchecked;
			}
			else if ( imageIndex == TriStateIndeterminateStateImageIndex )
			{
				return CheckState.Indeterminate;
			}
			else if ( imageIndex == TriStateNoStateImageIndex )
			{
				return CheckState.Unchecked;
			}
			else
			{
				Debug.Assert(
					false,
					string.Format(
					@"No check state for state image index {0} available.",
					imageIndex ) );
				return CheckState.Unchecked;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		private bool autoCheckSelected = true;

		/// <summary>
		/// Map a check state to a state image index.
		/// </summary>
		/// <param name="checkState">State of the check.</param>
		/// <returns></returns>
		private static int ConvertCheckStateToImageIndex(
			CheckState checkState )
		{
			switch ( checkState )
			{
				case CheckState.Checked:
					return TriStateCheckedStateImageIndex;
				case CheckState.Unchecked:
					return TriStateUncheckedStateImageIndex;
				case CheckState.Indeterminate:
					return TriStateIndeterminateStateImageIndex;
				default:
					Debug.Assert(
						false,
						string.Format(
						@"No state image for check state '{0}' available.",
						checkState ) );
					return TriStateNoStateImageIndex;
			}
		}

		/// <summary>
		/// Applies the given state to the given item.
		/// Raises events, too.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="action">The action.</param>
		/// <param name="stateImageIndex">Index of the state image.</param>
		/// <param name="raiseEvents">if set to <c>true</c> [raise events].</param>
		private void SetTriStateToItem(
			ListViewItem item,
			ListViewAction action,
			int stateImageIndex,
			bool raiseEvents )
		{
			bool canSet = true;

			if ( raiseEvents )
			{
				ItemCheckEventArgs args =
					new ItemCheckEventArgs(
					item.Index,
					ConvertStateImageIndexToCheckState(
					stateImageIndex ),
					ConvertStateImageIndexToCheckState(
					item.StateImageIndex ) );

				OnItemCheck( args );

				ItemCheckTriStateEventArgs triArgs =
					new ItemCheckTriStateEventArgs(
					item,
					action,
					ConvertStateImageIndexToCheckState(
					stateImageIndex ),
					ConvertStateImageIndexToCheckState(
					item.StateImageIndex ) );

				OnItemCheckTriState( triArgs );

				canSet = !triArgs.Cancel;
			}

			if ( canSet )
			{
				// Actually set.
				// THIS IS THE ONLY PLACE to set.
				item.StateImageIndex = stateImageIndex;

				if ( raiseEvents )
				{
					ItemCheckedEventArgs args =
						new ItemCheckedEventArgs( item );

					OnItemChecked( args );

					ItemCheckedTriStateEventArgs triArgs =
						new ItemCheckedTriStateEventArgs(
						item,
						action,
						item.StateImageIndex );

					OnItemCheckedTriState( triArgs );
				}
			}
		}

		/// <summary>
		/// Raises the ItemCheckTriState event.
		/// </summary>
		/// <param name="args">The ItemCheckTriStateEventArgs 
		/// instance containing the event data.</param>
		protected virtual void OnItemCheckTriState(
			ItemCheckTriStateEventArgs args )
		{
			if ( ItemCheckTriState != null )
			{
				ItemCheckTriState( this, args );
			}
		}

		/// <summary>
		/// Raises the ItemCheckedTriState event.
		/// </summary>
		/// <param name="args">The ItemCheckedTriStateEventArgs
		/// instance containing the event data.</param>
		protected virtual void OnItemCheckedTriState(
			ItemCheckedTriStateEventArgs args )
		{
			if ( ItemCheckedTriState != null )
			{
				ItemCheckedTriState( this, args );
			}

			CheckPerformAutoStepsTriStateChecked( args );
		}

		/// <summary>
		/// Does the apply state image index to item.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="stateImageIndex">Index of the state image.</param>
		/// <param name="raiseEvents">if set to <c>true</c> [raise events].</param>
		private void DoApplyStateImageIndexToItem(
			ListViewItem item,
			int stateImageIndex,
			bool raiseEvents )
		{
			SetTriStateToItem(
				item,
				ListViewAction.Unknown,
				stateImageIndex,
				raiseEvents );
		}

		/// <summary>
		/// Internal helper. Do not access directly but through the
		/// CheckedTriStateImageList property instead.
		/// </summary>
		private static ImageList _internalCheckedTriStateImageList = null;

		/// <summary>
		/// Access an image list with "CHECKED", "UNCHECKED" and
		/// "INDETERMINATE"�button states.
		/// The Tag properties of the images contain the respective value
		/// from the "System.Windows.Forms.CheckState" enumeration.
		/// </summary>
		/// <value>The checked tri state image list.</value>
		public static ImageList CheckedTriStateImageList
		{
			get
			{
				if ( _internalCheckedTriStateImageList == null )
				{
					_internalCheckedTriStateImageList =
						TriStateCheckBoxesTreeView.GenerateCheckedTriStateImageList();
				}

				return _internalCheckedTriStateImageList;
			}
		}

		/// <summary>
		/// The indexes into the state image list for the tri-state
		/// check boxes.
		/// </summary>
		private static readonly int TriStateNoStateImageIndex = -1;
		private static readonly int TriStateUncheckedStateImageIndex = 0;
		private static readonly int TriStateCheckedStateImageIndex = 1;
		private static readonly int TriStateIndeterminateStateImageIndex = 2;

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


Written By
Chief Technology Officer Zeta Software GmbH
Germany Germany
Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.

➡️ Give me a tip 🙂

In his free time, he does climbing, running and mountain biking. In 2012 he became a father of a cute boy and in 2014 of an awesome girl.

Some cool, free software from us:

Windows 10 Ereignisanzeige  
German Developer Community  
Free Test Management Software - Intuitive, competitive, Test Plans.  
Homepage erstellen - Intuitive, very easy to use.  
Offline-Homepage-Baukasten

Comments and Discussions