Click here to Skip to main content
15,892,927 members
Articles / Desktop Programming / WPF

A framework for comprehensive validation of user input

Rate me:
Please Sign up or sign in to vote.
4.70/5 (8 votes)
19 Jun 2012CPOL28 min read 31.3K   523   18  
Validation of input made as easy as possible for Windows.Forms, WPF, console-applications or any other purposes
// Copyright (c) 2005 - 2012, Andreas Ganzer. All Rights reserved.

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

namespace Ganzer.Windows.Forms.Validation
{
	//############################################################################
	/// <summary>
	/// The ValidatorLinkCollection class encapsulates a list of ValidatorLink
	/// objects.
	/// </summary>
	/// 
	public class ValidatorLinkCollection : IEnumerable<ValidatorLink>
	{
		#region fields

		private List<ValidatorLink> __links;

		#endregion

		#region properties

		/// <summary>
		/// Returns the link that contains the given control.
		/// </summary>
		/// 
		/// <param name="control">The control to search for.</param>
		/// 
		/// <returns>Returns the link that contains the given control. If the
		///   control could not be found, <c>null</c> is returned.</returns>
		/// 
		public ValidatorLink this[Control control]
		{
			get
			{
				return __links.Find(delegate( ValidatorLink link )
				{
					return ReferenceEquals(link.Control, control);
				});
			}
		}

		#endregion

		#region ctor/dtor

		/// <summary>
		/// Initializes this object with an empty list.
		/// </summary>
		/// 
		public ValidatorLinkCollection()
		{
			__links = new List<ValidatorLink>();
		}

		#endregion

		#region methods

		/// <summary>
		/// Inserts a link at the end of the list.
		/// </summary>
		/// 
		/// <param name="link">The link to insert.</param>
		/// 
		/// <exception cref="ArgumentNullException"><paramref name="link"/> is <c>null</c>.</exception>
		/// 
		public void Add( ValidatorLink link )
		{
			Debug.Assert(link != null);

			if( link == null )
				throw new ArgumentNullException("link", "ValidatorLinkCollection.Add");

			link.Disposed += ValidatorLink_Disposed;

			__links.Add(link);
		}

		/// <summary>
		/// Seraches the link of the given control and removes this from the list of
		/// links.
		/// </summary>
		/// 
		/// <param name="control">The control to remove.</param>
		/// <param name="disposeLink">If this is <c>true</c>, the found link will be
		///   disposed after removing.</param>
		/// 
		/// <returns>The removed link if <paramref name="disposeLink"/> is <c>false</c>.
		///   Otherwise, <c>null</c> is returned.</returns>
		/// 
		public ValidatorLink Remove( Control control, bool disposeLink )
		{
			ValidatorLink link = this[control];

			if( link != null && __links.Remove(link) )
			{
				link.Disposed -= ValidatorLink_Disposed;

				if( !disposeLink )
					return link;

				link.Dispose();
			}

			return null;
		}

		/// <summary>
		/// Removes the given from the list of links.
		/// </summary>
		/// 
		/// <param name="link">The link to remove.</param>
		/// <param name="disposeLink">If this is <c>true</c>, the given link will be
		///   disposed after removing.</param>
		/// 
		/// <returns><c>true</c> if <paramref name="link"/> is found and removed.</returns>
		/// 
		public bool Remove( ValidatorLink link, bool disposeLink )
		{
			if( !__links.Remove(link) )
				return false;

			link.Disposed -= ValidatorLink_Disposed;

			if( disposeLink )
				link.Dispose();

			return true;
		}

		/// <summary>
		/// Validates all controls in the list.
		/// </summary>
		/// 
		/// <returns><c>true</c> if the texts of all controls are valid; otherwise,
		///   <c>false</c> is returned.</returns>
		///   
		/// <remarks>
		/// This calls <see cref="ValidateAll(bool)">ValidateAll(true)</see>
		/// </remarks>
		/// 
		public bool ValidateAll()
		{
			return ValidateAll(true);
		}

		/// <summary>
		/// Validates all controls in the list.
		/// </summary>
		/// 
		/// <param name="stopOnError">Indicates whether validation is stopped on first
		///   error.</param>
		///   
		/// <returns><c>true</c> if the texts of all controls are valid; otherwise,
		///   <c>false</c> is returned.</returns>
		/// 
		/// <remarks>
		/// This iterates through all contained links and validates the input by calling
		/// <see cref="ValidatorLink.Validate()"/> for each link. The iteration stops for
		/// one of the following reasons:
		/// <list type="bullet">
		/// <item>
		/// <description>All controls are validated.</description>
		/// </item>
		/// <item>
		/// <description>The first validation fails and <paramref name="stopOnError"/> is
		/// <c>true</c></description>
		/// </item>
		/// <item>
		/// <description>A validation fails and the link of the invalid control contains
		/// the option <see cref="LinkOptions.ForceValid"/>.</description>
		/// </item>
		/// </list>
		/// </remarks>
		/// 
		public bool ValidateAll( bool stopOnError )
		{
			bool valid = true;

			foreach( ValidatorLink link in __links )
			{
				if( !link.Validate() )
				{
					valid = false;

					if( stopOnError || link.HasOption(LinkOptions.ForceValid) )
						return false;
				}
			}

			return valid;
		}

		/// <summary>
		/// Creates an enumerator for the list of controls.
		/// </summary>
		/// 
		/// <returns>The created enumerator.</returns>
		/// 
		public IEnumerator<ValidatorLink> GetEnumerator()
		{
			return __links.GetEnumerator();
		}

		/// <summary>
		/// Creates an enumerator for the list of controls.
		/// </summary>
		/// 
		/// <returns>The created enumerator.</returns>
		/// 
		IEnumerator IEnumerable.GetEnumerator()
		{
			return __links.GetEnumerator();
		}

		#endregion

		#region event handling

		/// <summary>
		/// Called if a stored link is disposed. Removes the link from this list.
		/// </summary>
		/// 
		/// <param name="sender">The link that is diposed.</param>
		/// <param name="e">The event arguments.</param>
		/// 
		void ValidatorLink_Disposed( object sender, EventArgs e )
		{
			__links.Remove(sender as ValidatorLink);
		}

		#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
Germany Germany
I am a software developer since many years and have worked on several large projects especially in financial sectors and the logistics industry.

My favorite programming languages are C, C++ und newly C#.

I am the architect and chief developer of Tricentis TDM Studio (former Q-up) - a generator that primarily creates template based synthetic data for software testing.

Comments and Discussions